Respostas:
Se você quiser apenas entrar em uma lista arbitrária:
"StringA" <> " " <> "StringB"
ou apenas use interpolação de string:
"#{a} #{b}"
Se o tamanho da sua lista for arbitrário:
Enum.join(["StringA", "StringB"], " ")
... todas as soluções acima retornarão
"StringA StringB"
Se o que você tem é uma lista arbitrária, você pode usá-lo Enum.join
, mas se for apenas por dois ou três, deve ser mais fácil ler a concatenação explícita de cadeias
"StringA" <> " " <> "StringB"
No entanto, muitas vezes você não precisa tê-lo como uma única string na memória se quiser produzi-lo através, por exemplo, da rede. Nesse caso, pode ser vantajoso usar um iolist (um tipo específico de uma lista profunda), que evita a cópia de dados. Por exemplo,
iex(1)> IO.puts(["StringA", " ", "StringB"])
StringA StringB
:ok
Como você teria essas strings como variáveis em algum lugar, usando uma lista profunda, evita alocar uma string totalmente nova apenas para produzi-la em outro lugar. Muitas funções no elixir / erlang entendem os iolistas, portanto, muitas vezes você não precisa fazer o trabalho extra.
Um Enum.reduce também funcionaria para o seu exemplo, não?
iex(4)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> x <> " " <> acc end)
"StringB StringA"
Depende do que você está tentando fazer. Se você está apenas tentando gravar uma nova variável, use:
Interpolação de string
a = "StringA"
b = "StringB"
"#{a} #{b}"
Concatentação de string: "StringA" <> " " <> "StringB
Enum.join()
: ["StringA", "StringB"] |> Enum.join(" ")
No entanto, como Uri mencionou, as IOLists também podem ser usadas:
["StringA", " ", "StringB"] |> IO.iodata_to_binary
As LIOs realmente terão o melhor desempenho se você precisar se preocupar com o consumo de recursos. O Big Nerd Ranch tem uma boa descrição dos ganhos de desempenho com listas de usuários da Internet.
Existem vários métodos, mas saber como ele lida com valores nulos pode determinar qual método você deve escolher.
Isso gerará um erro
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)
Isto apenas irá inserir uma string "" em branco:
iex(1)> "my name is #{nil}"
"my name is "
Como será isso:
iex(3)> Enum.join(["my name is", nil], " ")
"my name is "
Considere também os tipos. Com <>
você, não há transmissão gratuita:
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"
O desempenho na prática parece aproximadamente o mesmo:
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}
Portanto, realmente depende se você deseja travar ou não quando os valores interpolados são nil
ou do tipo errado.
Considere usar uma lista de E / S, se você tiver ["String1", "string2"] e usar iolist_to_binary / 1 nela, copiará essas strings para uma nova string. Se você tiver uma lista de E / S, basta produzi-la na maioria dos casos e ela será concatenada na porta. E isso é a chave, o tempo de execução não precisará fazer cópias dos dados, portanto é muito mais eficiente que a concatenação.
["StringA", "StringB"] |> Enum.join " "