Respuestas:
Compruebe Integer.parse/1y Float.parse/1.
Integer.parse/1más String.to_integer/1?
Integer.parse/1devuelve un :errorátomo si no tiene éxito. String.to_integer/1lanza un (FunctionClauseError).
Además de las funciones Integer.parse/1y Float.parse/1que sugirió José, también puede verificar String.to_integer/1y String.to_float/1.
Sugerencia: Véase también to_atom/1, to_char_list/1, to_existing_atom/1para otras conversiones.
Gracias a la gente de esta página, simplemente simplificando una respuesta aquí:
{intVal, ""} = Integer.parse(val)
ya que valida que se analizó toda la cadena (no solo un prefijo).
Hay 4 funciones para crear un número a partir de una cadena
String.to_integerfunciona bien pero String.to_floates 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_floatsolo puede manejar un flotante bien formateado, por ejemplo:, 1.0no 1(entero). Eso fue documentado en String.to_floatel documento de
Devuelve un flotante cuya representación de texto es una cadena.
cadena debe ser la representación de cadena de un flotante que incluya 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.parsedevuelve una tupla de 2 elementos, no el número que desea, por lo que ponerlo en canalización 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]
Usar elempara obtener el primer elemento de la tupla lo hace más corto y 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 char_list y luego usar Erlang to_integer/1o to_float/1.
P.ej
iex> {myInt, _} = :string.to_integer(to_char_list("23"))
{23, []}
iex> myInt
23
fn q -> {v, _} = Float.parse(q); v endque no me gusta. Me gusta usarlo Enum.map, por ejemplo, list |> Enum.map(&String.to_float/1)pero ¿string.to_float no funciona para números enteros?
Decimal.new("1") |> Decimal.to_integer
Decimal.new("1.0") |> Decimal.to_float
El problema con el uso Integer.parse/1es que analizará cualquier parte no numérica de la cadena siempre que esté al final. 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 mismo modo String.to_integer/1tiene 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]*$) dependiendo de su caso de uso.
Si desea convertir una cadena a cualquier 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)
String.to_integer/1