Odpowiedzi:
Jeśli chcesz tylko dołączyć do dowolnej listy:
"StringA" <> " " <> "StringB"
lub po prostu użyj interpolacji ciągów:
"#{a} #{b}"
Jeśli rozmiar listy jest dowolny:
Enum.join(["StringA", "StringB"], " ")
... wszystkie powyższe rozwiązania powrócą
"StringA StringB"
Jeśli masz dowolną listę, możesz użyć Enum.join
, ale jeśli jest to tylko dwie lub trzy, jawna konkatenacja ciągów powinna być łatwiejsza do odczytania
"StringA" <> " " <> "StringB"
Jednak często nie musisz mieć tego w pamięci jako pojedynczego ciągu, jeśli chcesz wyprowadzić go np. Przez sieć. W takim przypadku może być korzystne użycie iolist (szczególny rodzaj głębokiej listy), który chroni Cię przed kopiowaniem danych. Na przykład,
iex(1)> IO.puts(["StringA", " ", "StringB"])
StringA StringB
:ok
Ponieważ masz gdzieś te ciągi jako zmienne, używając głębokiej listy, unikasz przydzielania całego nowego ciągu tylko po to, aby wyprowadzić go gdzie indziej. Wiele funkcji w elixir / erlang obsługuje iolists, więc często nie trzeba wykonywać dodatkowej pracy.
Enum.reduce też by działało na twój przykład, nie?
iex(4)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> x <> " " <> acc end)
"StringB StringA"
To zależy od tego, co próbujesz zrobić. Jeśli po prostu próbujesz napisać do nowej zmiennej, po prostu użyj:
Interpolacja ciągów
a = "StringA"
b = "StringB"
"#{a} #{b}"
Konkatentacja ciągów: "StringA" <> " " <> "StringB
Enum.join()
: ["StringA", "StringB"] |> Enum.join(" ")
Jednak, jak wspomniał Uri, IOLists mogą być również używane:
["StringA", " ", "StringB"] |> IO.iodata_to_binary
IOList faktycznie będą najbardziej wydajne, jeśli musisz dbać o zużycie zasobów. Big Nerd Ranch ma dobry opis wzrostu wydajności z IOListami.
Istnieje wiele metod, ale wiedza o tym, jak obsługuje ona wartości zerowe, może określić, którą metodę należy wybrać.
Spowoduje to wyświetlenie błędu
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)
Spowoduje to wstawienie pustego ciągu „”:
iex(1)> "my name is #{nil}"
"my name is "
Podobnie jak to:
iex(3)> Enum.join(["my name is", nil], " ")
"my name is "
Weź również pod uwagę typy. Z <>
tobą nie dostaniesz żadnego darmowego odlewania:
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"
Wydajność w praktyce wydaje się mniej więcej taka sama:
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}
Tak naprawdę zależy od tego, czy chcesz się zawiesić, czy nie, gdy interpolowane wartości są nil
lub są niewłaściwego typu.
Rozważ użycie listy we / wy, jeśli masz ["String1", "string2"] i używasz na niej iolist_to_binary / 1, skopiujesz te ciągi do nowego łańcucha. Jeśli masz listę IO, możesz ją po prostu wyprowadzić w większości przypadków, a ona połączy ją na porcie. I to jest kluczowa rzecz, środowisko wykonawcze nie będzie musiało kopiować danych, więc jest znacznie bardziej wydajne niż konkatenacja.
["StringA", "StringB"] |> Enum.join " "