Réponses:
Si vous souhaitez simplement rejoindre une liste arbitraire:
"StringA" <> " " <> "StringB"
ou utilisez simplement l'interpolation de chaîne:
"#{a} #{b}"
Si la taille de votre liste est arbitraire:
Enum.join(["StringA", "StringB"], " ")
... toutes les solutions ci-dessus reviendront
"StringA StringB"
Si ce que vous avez est une liste arbitraire, vous pouvez l'utiliser Enum.join
, mais si c'est pour seulement deux ou trois, la concaténation de chaînes explicite devrait être plus facile à lire
"StringA" <> " " <> "StringB"
Cependant, souvent vous n'avez pas besoin de l'avoir sous forme de chaîne unique en mémoire si vous voulez le sortir par exemple via le réseau. Dans ce cas, il peut être avantageux d'utiliser une liste iolist (un type spécifique de liste détaillée), qui vous évite de copier des données. Par exemple,
iex(1)> IO.puts(["StringA", " ", "StringB"])
StringA StringB
:ok
Puisque vous auriez ces chaînes en tant que variables quelque part, en utilisant une liste complète, vous évitez d'allouer une toute nouvelle chaîne juste pour la sortir ailleurs. De nombreuses fonctions dans elixir / erlang comprennent les iolists, vous n'avez donc souvent pas besoin de faire le travail supplémentaire.
Un Enum.reduce fonctionnerait aussi pour votre exemple non?
iex(4)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> x <> " " <> acc end)
"StringB StringA"
Cela dépend de ce que vous essayez de faire. Si vous essayez simplement d'écrire dans une nouvelle variable, utilisez simplement soit:
Interpolation de chaîne
a = "StringA"
b = "StringB"
"#{a} #{b}"
Concatentation de chaînes: "StringA" <> " " <> "StringB
Enum.join()
: ["StringA", "StringB"] |> Enum.join(" ")
Cependant, comme Uri l'a mentionné, les LIO peuvent également être utilisées:
["StringA", " ", "StringB"] |> IO.iodata_to_binary
Les LIO seront en fait les plus performants si vous devez vous soucier de la consommation des ressources. Big Nerd Ranch a une bonne description des gains de performance avec les IOLists.
Il existe un certain nombre de méthodes, mais savoir comment il gère les valeurs nulles peut déterminer la méthode à choisir.
Cela lancera une erreur
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)
Cela insérera simplement une chaîne vide "":
iex(1)> "my name is #{nil}"
"my name is "
De même que ceci:
iex(3)> Enum.join(["my name is", nil], " ")
"my name is "
Considérez également les types. Avec <>
vous ne recevez aucun casting gratuit:
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"
Les performances en pratique semblent à peu près les mêmes:
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}
Donc, cela dépend vraiment si vous voulez planter ou non lorsque les valeurs interpolées sont nil
ou du mauvais type.
Pensez à utiliser une liste IO, si vous avez ["String1", "string2"] et que vous utilisez iolist_to_binary / 1 dessus, vous copiez ces chaînes dans une nouvelle chaîne. Si vous avez une liste d'E / S, vous pouvez simplement la sortir dans la plupart des cas et elle la concaténera sur le port. Et c'est la chose clé, le runtime n'aura pas besoin de faire des copies des données donc c'est beaucoup plus efficace que la concaténation.
["StringA", "StringB"] |> Enum.join " "