Antworten:
Wenn Sie sich nur einer beliebigen Liste anschließen möchten:
"StringA" <> " " <> "StringB"
oder verwenden Sie einfach die String-Interpolation:
"#{a} #{b}"
Wenn Ihre Listengröße beliebig ist:
Enum.join(["StringA", "StringB"], " ")
... alle oben genannten Lösungen werden zurückkehren
"StringA StringB"
Wenn Sie eine beliebige Liste haben, können Sie diese verwenden Enum.join
. Wenn es sich jedoch nur um zwei oder drei handelt, sollte die explizite Verkettung von Zeichenfolgen leichter zu lesen sein
"StringA" <> " " <> "StringB"
Oft müssen Sie es jedoch nicht als einzelne Zeichenfolge im Speicher haben, wenn Sie es beispielsweise über das Netzwerk ausgeben möchten. In diesem Fall kann es vorteilhaft sein, eine Iolist (einen bestimmten Typ einer tiefen Liste) zu verwenden, die Sie vor dem Kopieren von Daten bewahrt. Beispielsweise,
iex(1)> IO.puts(["StringA", " ", "StringB"])
StringA StringB
:ok
Da Sie diese Zeichenfolgen irgendwo als Variablen haben würden, vermeiden Sie durch die Verwendung einer tiefen Liste, eine ganz neue Zeichenfolge zuzuweisen, nur um sie an anderer Stelle auszugeben. Viele Funktionen in elixir / erlang verstehen Iolisten, sodass Sie die zusätzliche Arbeit oft nicht erledigen müssen.
Ein Enum.reduce würde auch für Ihr Beispiel funktionieren, nein?
iex(4)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> x <> " " <> acc end)
"StringB StringA"
Es hängt davon ab, was Sie versuchen zu tun. Wenn Sie nur versuchen, in eine neue Variable zu schreiben, verwenden Sie einfach Folgendes:
String-Interpolation
a = "StringA"
b = "StringB"
"#{a} #{b}"
String-Konzentration: "StringA" <> " " <> "StringB
Enum.join()
:: ["StringA", "StringB"] |> Enum.join(" ")
Wie Uri erwähnte, können IOListen jedoch auch verwendet werden:
["StringA", " ", "StringB"] |> IO.iodata_to_binary
IOListen werden tatsächlich am leistungsfähigsten sein, wenn Sie sich um den Ressourcenverbrauch kümmern müssen. Die Big Nerd Ranch hat einen guten Überblick über Leistungssteigerungen mit IOListen.
Es gibt eine Reihe von Methoden, aber wenn Sie wissen, wie mit Nullwerten umgegangen wird, können Sie bestimmen, welche Methode Sie wählen sollten.
Dies wird einen Fehler auslösen
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)
Dadurch wird nur eine leere "" Zeichenfolge eingefügt:
iex(1)> "my name is #{nil}"
"my name is "
Wie wird das:
iex(3)> Enum.join(["my name is", nil], " ")
"my name is "
Berücksichtigen Sie auch Typen. Mit <>
dir bekommst du kein Free Casting:
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"
Die Leistung in der Praxis scheint ungefähr gleich zu sein:
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}
Kommt also wirklich darauf an, ob du abstürzen willst oder nicht, wenn die interpolierten Werte nil
oder der falsche Typ sind.
Erwägen Sie die Verwendung einer E / A-Liste. Wenn Sie ["String1", "string2"] haben und iolist_to_binary / 1 verwenden, kopieren Sie diese Zeichenfolgen in eine neue Zeichenfolge. Wenn Sie eine E / A-Liste haben, können Sie diese in den meisten Fällen einfach ausgeben und sie wird am Port verkettet. Und das ist der Schlüssel, die Laufzeit muss keine Kopien der Daten erstellen, so dass es viel effizienter als die Verkettung ist.
["StringA", "StringB"] |> Enum.join " "