Saya perlu mengubah string menjadi nilai floating point atau integer. Tidak ada metode seperti,
string_to_integer
Jawaban:
Periksa Integer.parse/1
dan Float.parse/1
.
Integer.parse/1
lebih dari itu String.to_integer/1
?
Integer.parse/1
mengembalikan :error
atom jika tidak berhasil. String.to_integer/1
melempar a (FunctionClauseError)
.
Selain fungsi Integer.parse/1
dan Float.parse/1
yang disarankan José, Anda juga dapat memeriksa String.to_integer/1
dan String.to_float/1
.
Petunjuk: Lihat juga to_atom/1
, to_char_list/1
, to_existing_atom/1
untuk konversi lainnya.
Terima kasih teman-teman di halaman ini, hanya menyederhanakan jawaban di sini:
{intVal, ""} = Integer.parse(val)
karena memvalidasi bahwa seluruh string telah diurai (bukan hanya awalan).
Ada 4 fungsi untuk membuat angka dari string
String.to_integer
bekerja dengan baik tetapi String.to_float
lebih sulit:
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
Karena String.to_float
hanya dapat menangani float yang diformat dengan baik, misalnya:, 1.0
bukan 1
(integer). Itu didokumentasikan di String.to_float
doc
Mengembalikan float yang representasi teksnya adalah string.
string harus merupakan representasi string dari pelampung termasuk titik desimal. Untuk mengurai string tanpa koma desimal sebagai float maka Float.parse / 1 harus digunakan. Jika tidak, ArgumentError akan dimunculkan.
Tetapi Float.parse
mengembalikan tupel dari 2 elemen, bukan angka yang Anda inginkan, jadi memasukkannya ke dalam pipeline tidak "keren":
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]
Menggunakan elem
untuk mendapatkan elemen pertama dari tuple membuatnya lebih pendek dan lebih manis:
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]
Anda dapat mengubahnya menjadi char_list dan kemudian menggunakan Erlang to_integer/1
atau to_float/1
.
Misalnya
iex> {myInt, _} = :string.to_integer(to_char_list("23"))
{23, []}
iex> myInt
23
fn q -> {v, _} = Float.parse(q); v end
yang tidak saya sukai. Saya suka menggunakannya di Enum.map
, misalnya list |> Enum.map(&String.to_float/1)
tetapi string.to_float tidak berfungsi untuk bilangan bulat?
Decimal.new("1") |> Decimal.to_integer
Decimal.new("1.0") |> Decimal.to_float
Masalah dengan menggunakan Integer.parse/1
adalah bahwa is akan mengurai bagian non-numerik dari string selama berada di ujung ekor. Sebagai contoh:
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"}
Demikian pula String.to_integer/1
hasilnya sebagai berikut:
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")
Sebagai gantinya, validasi string terlebih dahulu.
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
Ekspresi reguler bisa lebih sederhana (misalnya ^[0-9]*$
) tergantung pada kasus penggunaan Anda.
Jika Anda ingin mengonversi string menjadi tipe numerik apa pun yang ada di dalam string & menghapus semua karakter lain, ini mungkin berlebihan, tetapi akan mengembalikan float jika float atau int jika int atau nil jika string tidak berisi tipe numerik.
@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)
String.to_integer/1