Respuestas:
Si solo quieres unirte a alguna lista arbitraria:
"StringA" <> " " <> "StringB"
o simplemente use la interpolación de cadenas:
"#{a} #{b}"
Si el tamaño de su lista es arbitrario:
Enum.join(["StringA", "StringB"], " ")
... todas las soluciones anteriores volverán
"StringA StringB"
Si lo que tiene es una lista arbitraria, puede usarla Enum.join
, pero si es solo para dos o tres, la concatenación explícita de cadenas debería ser más fácil de leer
"StringA" <> " " <> "StringB"
Sin embargo, a menudo no necesita tenerlo como una sola cadena en la memoria si va a generarlo, por ejemplo, a través de la red. En ese caso, puede ser ventajoso usar una iolist (un tipo específico de una lista profunda), que le ahorra copiar datos. Por ejemplo,
iex(1)> IO.puts(["StringA", " ", "StringB"])
StringA StringB
:ok
Dado que tendría esas cadenas como variables en alguna parte, al usar una lista profunda, evita asignar una cadena completamente nueva solo para generarla en otro lugar. Muchas funciones en elixir / erlang entienden las iolistas, por lo que a menudo no necesitaría hacer el trabajo adicional.
Un Enum.reduce también funcionaría para su ejemplo, ¿no?
iex(4)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> x <> " " <> acc end)
"StringB StringA"
Depende de lo que intentes hacer. Si solo está tratando de escribir en una nueva variable, simplemente use:
Interpolación de cuerdas
a = "StringA"
b = "StringB"
"#{a} #{b}"
Concatenación de cadenas: "StringA" <> " " <> "StringB
Enum.join()
: ["StringA", "StringB"] |> Enum.join(" ")
Sin embargo, como mencionó Uri, las LIO también se pueden usar:
["StringA", " ", "StringB"] |> IO.iodata_to_binary
Los IOListas realmente serán los más eficaces si necesita preocuparse por el consumo de recursos. Big Nerd Ranch tiene una buena reseña sobre las ganancias de rendimiento con IOLists.
Hay varios métodos, pero saber cómo maneja los valores nulos puede determinar qué método debe elegir.
Esto arrojará un error
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)
Esto solo insertará una cadena "" en blanco:
iex(1)> "my name is #{nil}"
"my name is "
Como será esto:
iex(3)> Enum.join(["my name is", nil], " ")
"my name is "
Considere también los tipos. Contigo <>
no obtienes ningún casting gratis:
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"
El rendimiento en la práctica parece más o menos el mismo:
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}
Entonces, realmente depende de si desea bloquearse o no cuando los valores interpolados son nil
o del tipo incorrecto.
Considere usar una Lista de E / S, si tiene ["Cadena1", "cadena2"] y usa iolist_to_binary / 1, copiará esas cadenas en una nueva cadena. Si tiene una lista de E / S, puede generarla en la mayoría de los casos y la concatenará en el puerto. Y esta es la clave, el tiempo de ejecución no necesitará hacer copias de los datos, por lo que es mucho más eficiente que la concatenación.
["StringA", "StringB"] |> Enum.join " "