J'ai besoin de convertir une chaîne en une valeur à virgule flottante ou un entier. Il n'y avait pas de méthode telle que
string_to_integer
Vérifier Integer.parse/1
et Float.parse/1
.
En plus de Integer.parse/1
et Float.parse/1
fonctions que José vous a suggéré de vérifier également String.to_integer/1
et String.to_float/1
.
Indice: voir aussi to_atom/1
, to_char_list/1
, to_existing_atom/1
pour d'autres conversions.
Merci aux gens sur cette page, simplifiant simplement une réponse ici:
{intVal, ""} = Integer.parse(val)
car il valide que la chaîne entière a été analysée (pas seulement un préfixe).
Il y a 4 fonctions pour créer un nombre à partir d'une chaîne
String.to_integer
Fonctionne bien mais String.to_float
Est plus difficile:
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
Comme String.to_float
Ne peut gérer que des fonds flottants bien formatés, par exemple: 1.0
, Pas 1
(Entier). Cela a été documenté dans la documentation de String.to_float
Retourne un float dont la représentation textuelle est une chaîne.
string doit être la représentation sous forme de chaîne d'un float incluant un point décimal. Afin d'analyser une chaîne sans virgule décimale en tant que float, il convient d'utiliser Float.parse/1. Sinon, une ArgumentError sera levée.
Mais Float.parse
Renvoie un tuple de 2 éléments, pas le nombre que vous voulez, alors le mettre en pipeline n'est pas "cool":
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]
Utiliser elem
pour obtenir le premier élément de Tuple le rend plus court et plus doux:
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]
Vous pouvez le convertir en une liste de caractères puis utiliser le fichier Erlang to_integer/1
ou to_float/1
.
Par exemple.
iex> {myInt, _} = :string.to_integer(to_char_list("23"))
{23, []}
iex> myInt
23
Le problème avec Integer.parse/1
_ c'est-à-dire qu'il analysera toute partie non numérique de la chaîne tant qu'elle se trouvera à la fin. Par exemple:
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"}
De même String.to_integer/1
a les résultats suivants:
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")
Au lieu de cela, validez la chaîne en premier.
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
L’expression régulière pourrait être plus simple (par exemple, ^[0-9]*$
) en fonction de votre cas d'utilisation.
Decimal.new("1") |> Decimal.to_integer
Decimal.new("1.0") |> Decimal.to_float
Si vous vouliez convertir une chaîne en un type numérique quelconque et supprimer tous les autres caractères, ceci est probablement excessif, mais vous renverrez un float s'il s'agit d'un float ou un entier si c'est un entier ou nil si la chaîne ne contient pas un type numérique.
@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)