Elixir文字列を整数または浮動小数点数に変換します


97

文字列を浮動小数点値または整数に変換する必要があります。そのような方法はありませんでした、

string_to_integer

回答:


153

チェックInteger.parse/1してFloat.parse/1


36
これはタプル(成功した場合)を返し、整数を直接返さないことに注意してください。それをしたい場合は、@ SzymonJeżの回答を参照してくださいString.to_integer/1

6
Integer.parse/1以上使用する理由はありますString.to_integer/1か?
Ian Vaughan

10
@IanVaughan Integer.parse/1は、:error失敗するとアトムを返します。String.to_integer/1をスローし(FunctionClauseError)ます。
Jonathan Soifer 2017

52

加えInteger.parse/1そしてFloat.parse/1ホセは、あなたもチェックすることが示唆された機能String.to_integer/1String.to_float/1

ヒント:また、参照してくださいto_atom/1to_char_list/1to_existing_atom/1他の変換のために。


27

このページの人々に感謝します、ここで答えを単純化するだけです:

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

文字列全体が(接頭辞だけでなく)解析されたことを検証するためです。


これは、valが純粋な整数でない場合にエラーをスローします。変換が成功したことを確認するために、結果にケースを追加しました。入力が「x3」または「3x」のどちらであるかをあまり気にしないので、2番目の句は:errorまたは空でない2番目の文字列をキャッチするために一般的です。
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唯一例えば、よくフォーマットされたフロートを扱うことができます1.0、ではない1(整数)。記載されたことString.to_floatのドキュメント

テキスト表現が文字列であるフロートを返します。

stringは、小数点を含むfloatの文字列表現でなければなりません。小数点のない文字列を浮動小数点数として解析するには、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/1またはを使用できますto_float/1

例えば

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

iex> myInt
23

関数でそれを使用するには?私の最善の解決策はfn q -> {v, _} = Float.parse(q); v end、私が気に入らないことです。私はそれをで使用したいのですがEnum.maplist |> Enum.map(&String.to_float/1)string.to_floatは整数では機能しませんか?
Zhomart 2017年

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

使用の問題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、文字列が含まれていない場合は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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.