Преобразование строки эликсира в целое число или float
Мне нужно преобразовать строку в значение с плавающей запятой или целое число. Не было такого метода, как,
string_to_integer
8 ответов:
Регистрация
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)
спасибо @dimagog за комментарий
вы можете преобразовать его в 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
- целое число.разбирать, плавать.разбор
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
может обрабатывать только хорошо отформатированный поплавок, например:1.0
, а не1
(целое число). Это было задокументировано вString.to_float
'ы доквозвращает float, текстовое представление которого является строкой.
строка должна быть строковым представлением с плавающей запятой, включая десятичную точку. Для того, чтобы разобрать строку без десятичной точки в качестве поплавка, то Float.следует использовать parse / 1. В противном случае будет поднят аргумент.
но
Float.parse
возвращает кортеж из 2 элементов, а не число, которое вы хотите, поэтому поместите его в конвейер не "круто":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]*$
) в зависимости от вашего варианта использования.
Если вы хотите преобразовать строку в любой числовой тип внутри строки и удалить все другие символы, это, вероятно, излишне, но вернет 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)