【问题标题】:Convert Elixir string to integer or float将 Elixir 字符串转换为整数或浮点数
【发布时间】:2014-04-29 21:02:44
【问题描述】:

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

string_to_integer

【问题讨论】:

    标签: elixir


    【解决方案1】:

    【讨论】:

    • 请注意,这将返回一个元组(如果成功)而不是直接返回整数。如果您想这样做,请参阅@Szymon Jeż 回复 String.to_integer/1
    • 有什么理由使用Integer.parse/1而不是String.to_integer/1
    • @IanVaughan Integer.parse/1 如果不成功,则返回 :error 原子。 String.to_integer/1 抛出 (FunctionClauseError)
    • 为了补充乔纳森的观点,String.to_float("0") 会引发错误,而Float.parse("0") 返回{0.0, ""}。当我的字符串可能不包含小数点时,这允许我使用单个函数。
    【解决方案2】:

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

    提示:另请参阅to_atom/1,to_char_list/1,to_existing_atom/1了解其他转换。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

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

      有 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 只能处理格式良好的浮点数,例如: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]
      

      【讨论】:

        【解决方案5】:

        您可以将其转换为 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 不适用于整数?
        【解决方案6】:

        使用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]*$)。

        【讨论】:

          【解决方案7】:
          Decimal.new("1") |> Decimal.to_integer
          Decimal.new("1.0") |> Decimal.to_float
          

          【讨论】:

          • IMO 这是最好的答案。
          • 我收到这个错误:** (UndefinedFunctionError) function Decimal.new/1 is undefined (module Decimal is not available)
          【解决方案8】:

          如果您想将字符串转换为字符串中的任何数字类型并删除所有其他字符,这可能是矫枉过正,但如果它是浮点数,则返回一个浮点数;如果它是整数,则返回一个整数;如果是字符串,则返回 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)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-06
            • 2011-11-25
            • 1970-01-01
            • 2016-05-02
            相关资源
            最近更新 更多