Мне нужно преобразовать строку в значение с плавающей запятой или целое число. Не было никакого метода, такого как
string_to_integer
Мне нужно преобразовать строку в значение с плавающей запятой или целое число. Не было никакого метода, такого как
string_to_integer
Проверьте Integer.parse/1
и Float.parse/1
.
В дополнение к функциям Integer.parse/1
и Float.parse/1
, которые предложил Хосе, вы также можете проверить String.to_integer/1
и String.to_float/1
.
Подсказка: см. также to_atom/1
, to_char_list/1
, to_existing_atom/1
для других преобразований.
Спасибо, ребята на этой странице, просто упростив ответ здесь:
{intVal, ""} = Integer.parse(val)
так как он проверяет, что вся строка была проанализирована (а не просто префикс).
Вы можете преобразовать его в char_list, а затем использовать Erlang to_integer/1
или to_float/1
.
например.
iex> {myInt, _} = :string.to_integer(to_char_list("23"))
{23, []}
iex> myInt
23
Существует 4 функции для создания числа из строки
String.to_integer
работает красиво, но String.to_float
является более жестким:
iex()> "1 2 3 10 100" |> String.split |> Enum.map(&String.to_integer/1)
[1, 2, 3, 10, 100]
iex()> "1.0 1 3 10 100" |> String.split |> Enum.map(&String.to_float/1)
** (ArgumentError) argument error
:erlang.binary_to_float("1")
(elixir) lib/enum.ex:1270: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/enum.ex:1270: Enum."-map/2-lists^map/1-0-"/2
Поскольку String.to_float
может обрабатывать только форматированный float, например: 1.0
, not 1
(integer). Это было зарегистрировано в String.to_float
doc
Возвращает float, текстовое представление которого является строкой.
Строкадолжна быть строковым представлением поплавка, включая десятичную точку. Чтобы разобрать строку без десятичной точки в качестве поплавка, следует использовать Float.parse/1. В противном случае будет создан ArgumentError.
Но Float.parse
возвращает кортеж из двух элементов, а не числа, которое вы хотите, поэтому поместить его в конвейер не "круто":
iex()> "1.0 1 3 10 100" |> String.split \
|> Enum.map(fn n -> {v, _} = Float.parse(n); v end)
[1.0, 1.0, 3.0, 10.0, 100.0]
Используя elem
, чтобы получить первый элемент из кортежа, сделайте его короче и слаще:
iex()> "1.0 1 3 10 100" |> String.split \
|> Enum.map(fn n -> Float.parse(n) |> elem(0) end)
[1.0, 1.0, 3.0, 10.0, 100.0]
Проблема с использованием Integer.parse/1
заключается в том, что будет анализировать любую нечисловую часть строки, если она находится в конце. Например:
Integer.parse("01") # {1, ""}
Integer.parse("01.2") # {1, ".2"}
Integer.parse("0-1") # {0, "-1"}
Integer.parse("-01") # {-1, ""}
Integer.parse("x-01") # :error
Integer.parse("0-1x") # {0, "-1x"}
Аналогично String.to_integer/1
имеет следующие результаты:
String.to_integer("01") # 1
String.to_integer("01.2") # ** (ArgumentError) argument error :erlang.binary_to_integer("01.2")
String.to_integer("0-1") # ** (ArgumentError) argument error :erlang.binary_to_integer("01.2")
String.to_integer("-01") # -1
String.to_integer("x-01") # ** (ArgumentError) argument error :erlang.binary_to_integer("01.2")
String.to_integer("0-1x") # ** (ArgumentError) argument error :erlang.binary_to_integer("01.2")
Вместо этого сначала проверьте строку.
re = Regex.compile!("^[+-]?[0-9]*\.?[0-9]*$")
Regex.match?(re, "01") # true
Regex.match?(re, "01.2") # true
Regex.match?(re, "0-1") # false
Regex.match?(re, "-01") # true
Regex.match?(re, "x-01") # false
Regex.match?(re, "0-1x") # false
Регулярное выражение может быть проще (например, ^[0-9]*$
) в зависимости от вашего варианта использования.
Decimal.new("1") |> Decimal.to_integer
Decimal.new("1.0") |> Decimal.to_float
Если вы хотите преобразовать строку в любой числовой тип внутри строки и удалить все остальные символы, это, вероятно, слишком велико, но вернет float, если это float или int, если это int или nil, если строка не содержит числовой тип.
@spec string_to_numeric(binary()) :: float() | number() | nil
def string_to_numeric(val) when is_binary(val), do: _string_to_numeric(Regex.replace(~r{[^\d\.]}, val, ""))
defp _string_to_numeric(val) when is_binary(val), do: _string_to_numeric(Integer.parse(val), val)
defp _string_to_numeric(:error, _val), do: nil
defp _string_to_numeric({num, ""}, _val), do: num
defp _string_to_numeric({num, ".0"}, _val), do: num
defp _string_to_numeric({_num, _str}, val), do: elem(Float.parse(val), 0)