エリクサーで文字列を結合する方法は?


158

次のように、リスト内の2つの文字列をスペースで結合するにはどうすればよいですか。

["StringA", "StringB"]

なる

"StringA StringB"

回答:


220

任意のリストに参加したいだけの場合:

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

または単に文字列補間を使用します:

 "#{a} #{b}"

リストのサイズが任意の場合:

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

...上記のすべてのソリューションが返されます

"StringA StringB"

36
パイプライン演算子を使用した代替構文: ["StringA", "StringB"] |> Enum.join " "
Ryan Cromwell

11
実際にパイプ操作を行う必要がない場合は、パイプライン演算子を使用しないでください。
Carlos

3
@EdMelo Careが理由を詳しく説明しますか?関数呼び出しをネストすることで同じ動作を実現できるため、技術的にはパイプ操作を本当に「必要」とすることはありません。
Schrockwell

8
@Schrockwellええ、「すべき」は多すぎました。つまり、この場合は読みやすさが向上しないため、単純な関数呼び出しを行うと、思考がより明確になります。
カルロス、

3
あなたはそれを知っていることを潜在的な雇用主に示すために、できるだけ多くのElixir言語を使用するべきです。したがって、上記のすべてのソリューションを同じファイルで使用します。
rodmclaughlin

61

あなたが持っているものが任意のリストであるなら、あなたは使うことができますEnum.joinが、それが2つか3つだけの場合、明示的な文字列連結は読みやすくなるはずです

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

ただし、ネットワークなどを介して出力する場合は、メモリ内に単一の文字列として持つ必要はありません。その場合、iolist(特定のタイプのディープリスト)を使用すると、データをコピーする必要がなくなります。例えば、

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

ディープリストを使用すると、これらの文字列が変数としてどこかにあるため、新しい文字列をまったく別の場所に出力するためだけに割り当てることは避けます。elixir / erlangの多くの関数はiolistを理解するので、多くの場合、追加の作業を行う必要はありません。


パイプコマンドの最後に何かを追加する必要がある場合 "String" |>(&(&1 <> "\ n"))()
hwatkins

9

完全を期すために、文字列補間を使用することもできます。

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

5

リストにスペースを追加することに問題がなければ、iolistとして扱うことができます。

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

これにより、メモリ内の文字列を複製しないため、パフォーマンスが向上します。


4

Enum.reduceはあなたの例でも機能しますか?

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


はい、ただし逆が必要ですEnum.reduce(["a"、 "b"、 "c"] |> Enum.reverse、fn(x、acc)-> x <> "" <> acc end) "ab c "
Andrei Sura

これは、reduceを使用できる他のケースに一般化されるため、これが最良の答えであると個人的に考えています。R.の "do.call"のアイデアに言及
Thomas Browne

3

それはあなたが何をしようとしているのかに依存します。新しい変数に書き出すだけの場合は、次のいずれかを使用します。

  • 文字列補間

    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を使用たパフォーマンスの向上に関して優れた評価を得ています。


2

いくつかの方法がありますが、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間違った型である場合にクラッシュするかどうかに本当に依存します。



0

IOリストの使用を検討してください。["String1"、 "string2"]があり、それにiolist_to_binary / 1を使用している場合は、それらの文字列を新しい文字列にコピーします。IOリストがある場合は、ほとんどの場合それを出力するだけでポートに連結されます。そしてこれが重要です。ランタイムはデータのコピーを作成する必要がないため、連結よりもはるかに効率的です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.