将Elixir字符串转换为整数或浮点数


97

我需要将字符串转换为浮点值或整数。没有这样的方法,

string_to_integer

Answers:



52

除了José建议的Integer.parse/1Float.parse/1功能之外,您还可以检查String.to_integer/1String.to_float/1

提示:有关其他转换,另请参见to_atom/1,。to_char_list/1to_existing_atom/1


27

感谢此页面上的人们,只是在这里简化答案:

{intVal, ""} = Integer.parse(val)

因为它验证了整个字符串都已解析(不仅仅是前缀)。


如果val不是纯粹的整数,则将引发错误。我在结果上添加了一个案例,以确保转换成功。第二个子句可以通用来捕获:error或第二个非空字符串,因为您不太在乎输入是“ x3”还是“ 3x”。
Sinc

14

有4个函数可从字符串创建数字

  • String.to_integer,String.to_float
  • Integer.parse,Float.parse

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只能处理格式正确的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]

11

您可以将其转换为char_list,然后使用Erlang to_integer/1to_float/1

例如

iex> {myInt, _} = :string.to_integer(to_char_list("23"))
{23, []}

iex> myInt
23

如何在函数中使用它?我最好的解决方案是fn q -> {v, _} = Float.parse(q); v end我不喜欢的解决方案。我喜欢在中使用它Enum.map,例如list |> Enum.map(&String.to_float/1)string.to_float对整数不起作用?
Zhomart '17

5
Decimal.new("1") |> Decimal.to_integer
Decimal.new("1.0") |> Decimal.to_float

1
IMO这是最好的答案。
Marcin Adamczyk

我收到此错误:**(UndefinedFunctionError)函数Decimal.new/1未定义(模块Decimal不可用)
Daniel Cukier

4

using的问题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]*$根据您的用例,正则表达式可能更简单(例如)。


0

如果您想将字符串转换为字符串中的任何数字类型并删除所有其他字符,这可能会过大,但是如果其为float则返回float,如果其不包含int则返回int或null数字类型。

@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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.