tutorial - elixir también se buscó
Convierte una cuerda Elixir en un entero o en un flotador (8)
Necesito convertir una cadena a un valor de punto flotante o un número entero. No hubo un método como,
string_to_integer
Además de las funciones Integer.parse/1
y Float.parse/1
que José sugirió, también puede verificar String.to_integer/1
y String.to_float/1
.
Sugerencia: vea también to_atom/1
, to_char_list/1
, to_existing_atom/1
para otras conversiones.
Comprueba Integer.parse/1
y Float.parse/1
.
El problema con el uso de Integer.parse/1
es que se analizará cualquier parte no numérica de la cadena, siempre que se encuentre en el extremo posterior. Por ejemplo:
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"}
Del String.to_integer/1
modo, String.to_integer/1
tiene los siguientes resultados:
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")
En su lugar, valide la cadena primero.
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
La expresión regular podría ser más simple (por ejemplo, ^[0-9]*$
) según su caso de uso.
Gracias amigos en esta página, simplemente simplificando una respuesta aquí:
{intVal, ""} = Integer.parse(val)
Gracias a @dimagog por el comentario
Hay 4 funciones para crear un número a partir de una cadena
- String.to_integer, String.to_float
- Integer.parse, Float.parse
String.to_integer
funciona bien pero String.to_float
es más difícil:
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
Como String.to_float
solo puede manejar float bien formateado, p. Ej .: 1.0
, not 1
(integer). Eso fue documentado en el documento de String.to_float
Devuelve un flotante cuya representación de texto es una cadena.
cadena debe ser la representación de cadena de un flotante, incluyendo un punto decimal. Para analizar una cadena sin punto decimal como flotante, se debe usar Float.parse / 1. De lo contrario, se generará un ArgumentError.
Pero Float.parse
devuelve una tupla de 2 elementos, no el número que desea, así que ponerlo en la tubería no es "genial":
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]
El uso de elem
para obtener el primer elemento de la tupla lo hace más corto y más dulce:
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]
Puede convertirlo a una char_list y luego usar Erlang to_integer/1
o to_float/1
.
P.ej
iex> {myInt, _} = :string.to_integer(to_char_list("23"))
{23, []}
iex> myInt
23
Si desea convertir una cadena al tipo numérico que está dentro de la cadena y eliminar todos los demás caracteres, esto probablemente sea excesivo, pero devolverá un flotante si es un flotante o un int si es un int o nil si la cadena no contiene un tipo numérico
@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)
Decimal.new("1") |> Decimal.to_integer
Decimal.new("1.0") |> Decimal.to_float