code

Elixir 문자열을 정수 또는 부동 소수점으로 변환

codestyles 2020. 10. 4. 11:18
반응형

Elixir 문자열을 정수 또는 부동 소수점으로 변환


문자열을 부동 소수점 값 또는 정수로 변환해야합니다. 다음과 같은 방법이 없었습니다.

string_to_integer

확인 Integer.parse/1Float.parse/1.


José가 제안한 Integer.parse/1Float.parse/1기능 외에도 String.to_integer/1String.to_float/1.

힌트 : 참조 to_atom/1, to_char_list/1, to_existing_atom/1다른 변환을 위해.


이 페이지의 사람들에게 감사드립니다. 여기에 답변을 단순화하십시오.

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

전체 문자열이 (단지 접두사가 아닌) 구문 분석되었는지 확인합니다.


char_list로 변환 한 다음 Erlang to_integer/1또는 to_float/1.

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

iex> myInt
23

문자열에서 숫자를 생성하는 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]

사용의 문제 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")

Instead, validate the string first.

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

The regular expression could be simpler (e.g. ^[0-9]*$) depending on your use case.


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

If you wanted to convert a string to whatever numeric type is within the string & remove all other characters, this is probably overkill, but will return a float if its a float or an int if its an int or nil if the string does not contain an numeric type.

@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)

참고URL : https://stackoverflow.com/questions/22576658/convert-elixir-string-to-integer-or-float

반응형