[elixir] 엘릭서에서 문자열을 결합하는 방법?

공백이있는 목록에서 두 문자열을 결합하는 방법은 다음과 같습니다.

["StringA", "StringB"]

된다

"StringA StringB"



답변

임의의 목록에 가입하려는 경우 :

"StringA" <> " " <> "StringB"

또는 문자열 보간을 사용하십시오.

 "#{a} #{b}"

목록 크기가 임의 인 경우 :

Enum.join(["StringA", "StringB"], " ")

… 위의 모든 솔루션이 반환됩니다

"StringA StringB"


답변

가지고있는 것이 임의의 목록이라면을 사용할 수 Enum.join있지만 2 ~ 3 인 경우 명시 적 문자열 연결을 쉽게 읽을 수 있어야합니다

"StringA" <> " " <> "StringB"

그러나 네트워크 등을 통해 출력하려는 ​​경우 종종 메모리에서 단일 문자열로 가질 필요가 없습니다. 이 경우, 데이터 복사에서 절약되는 iolist (특정 유형의 딥 목록)를 사용하는 것이 유리할 수 있습니다. 예를 들어

iex(1)> IO.puts(["StringA", " ", "StringB"])
StringA StringB
:ok

딥 목록을 사용하여 해당 문자열을 변수로 사용할 수 있으므로 다른 곳에서 출력하기 위해 완전히 새로운 문자열을 할당하지 마십시오. elixir / erlang의 많은 함수는 iolist를 이해하므로 추가 작업을 수행 할 필요가없는 경우가 많습니다.


답변

완성도에 대한 응답으로 문자열 보간 을 사용할 수도 있습니다 .

iex(1)> [a, b] = ["StringA", "StringB"]
iex(2)> "#{a} #{b}"
"StringA StringB"


답변

목록에 공백을 추가해도 괜찮다면이를 iolist로 취급 할 수 있습니다.

["StringA", " ", "StringB"] |> IO.iodata_to_binary # "StringA StringB"

메모리의 문자열을 복제하지 않으므로 성능이 약간 향상됩니다.


답변

Enum.reduce도 귀하의 예에 맞지 않습니까?

iex(4)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> x <> " " <> acc end)
"StringB StringA"


답변

당신이하려는 일에 달려 있습니다. 새 변수에 쓰려고하면 다음 중 하나를 사용하십시오.

  • 문자열 보간

    a = "StringA"
    b = "StringB"
    "#{a} #{b}"
    
  • 문자열 연결 : "StringA" <> " " <> "StringB

  • Enum.join(): ["StringA", "StringB"] |> Enum.join(" ")

그러나 Uri가 언급했듯이 IOList를 사용할 수도 있습니다.

["StringA", " ", "StringB"] |> IO.iodata_to_binary

리소스 소비에 관심이 있다면 IOList는 실제로 가장 성능이 우수합니다. Big Nerd Ranch는 IOList를 통한 성능 향상에 대해 잘 작성 했습니다.


답변

여러 가지 방법이 있지만 nil 값을 처리하는 방법을 알면 선택해야 할 방법을 결정할 수 있습니다.

오류가 발생합니다

iex(4)> "my name is " <> "adam"
"my name is adam"

iex(1)> "my name is " <> nil
** (ArgumentError) expected binary argument in <> operator but got: nil
    (elixir) lib/kernel.ex:1767: Kernel.wrap_concatenation/3
    (elixir) lib/kernel.ex:1758: Kernel.extract_concatenations/2
    (elixir) lib/kernel.ex:1754: Kernel.extract_concatenations/2
    (elixir) expanding macro: Kernel.<>/2
    iex:1: (file)

이것은 빈 “”문자열을 삽입합니다 :

iex(1)> "my name is #{nil}"
"my name is "

이것처럼

iex(3)> Enum.join(["my name is", nil], " ")
"my name is "

유형도 고려하십시오. 함께 <>하면 어떤 자유 캐스팅을하지 않는다 :

iex(5)> "my name is " <> 1
** (ArgumentError) expected binary argument in <> operator but got: 1
    (elixir) lib/kernel.ex:1767: Kernel.wrap_concatenation/3
    (elixir) lib/kernel.ex:1758: Kernel.extract_concatenations/2
    (elixir) lib/kernel.ex:1754: Kernel.extract_concatenations/2
    (elixir) expanding macro: Kernel.<>/2
    iex:5: (file)

iex(5)> "my name is #{1}"
"my name is 1"

iex(7)> Enum.join(["my name is", 1], " ")
"my name is 1"

실제로 성능은 거의 같습니다.

iex(22)> :timer.tc(fn -> Enum.each(1..10_000_000, fn _ -> "my name is " <> "adam" end) end)
{8023855, :ok}
iex(23)> :timer.tc(fn -> Enum.each(1..10_000_000, fn _ -> "my name is " <> "adam" end) end)
{8528052, :ok}
iex(24)> :timer.tc(fn -> Enum.each(1..10_000_000, fn _ -> "my name is " <> "adam" end) end)
{7778532, :ok}
iex(25)> :timer.tc(fn -> Enum.each(1..10_000_000, fn _ -> "my name is #{"adam"}" end) end)
{7620582, :ok}
iex(26)> :timer.tc(fn -> Enum.each(1..10_000_000, fn _ -> "my name is #{"adam"}" end) end)
{7782710, :ok}
iex(27)> :timer.tc(fn -> Enum.each(1..10_000_000, fn _ -> "my name is #{"adam"}" end) end)
{7743727, :ok}

따라서 보간 된 값이 nil잘못되었거나 유형이 잘못된 경우 충돌 여부를 결정 합니다.