我需要将字符串转换为浮点值或整数。没有这样的方法,
string_to_integer
除了 José 建议的
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
了解其他转换。
感谢本页的人们,只是在这里简化答案:
{int_val, ""} = Integer.parse(val)
因为它验证整个字符串已被解析(而不仅仅是前缀)。
有 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
只能处理格式正确的浮点数,例如:1.0
,而不是 1
(整数)。这已记录在 String.to_float
的文档中
返回一个浮点数,其文本表示形式为字符串。
string 必须是包含小数点的浮点数的字符串表示形式。为了将没有小数点的字符串解析为浮点数,则应使用 Float.parse/1 。否则,将会引发 ArgumentError。
但是
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]
您可以将其转换为 char_list,然后使用 Erlang
to_integer/1
或 to_float/1
。
例如
iex> {myInt, _} = :string.to_integer(to_char_list("23"))
{23, []}
iex> myInt
23
使用
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
如果您想将字符串转换为字符串中的任何数字类型并删除所有其他字符,这可能有点过头了,但如果它是浮点型,则返回浮点数;如果它是 int,则返回 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)
您可以使用
to_integer/1
和 to_float/1
String.to_integer(numstr || "0")
String.to_float(numstr || "0.0")