如何在带有空格的列表中连接两个字符串,例如:
["StringA", "StringB"]
变为
"StringA StringB"
答案 0 :(得分:178)
如果您只想加入一些任意列表:
"StringA" <> " " <> "StringB"
或只使用字符串插值:
"#{a} #{b}"
如果您的列表大小是任意的:
Enum.join(["StringA", "StringB"], " ")
......以上所有解决方案都将返回
"StringA StringB"
答案 1 :(得分:57)
如果你拥有的是一个任意列表,那么你可以使用Enum.join
,但如果只有两个或三个,显式字符串连接应该更容易阅读
"StringA" <> " " <> "StringB"
然而,如果您要通过例如输出它,通常不需要将它作为单个字符串存储在内存中。网络。在这种情况下,使用iolist(特定类型的深度列表)可能是有利的,这可以避免复制数据。例如,
iex(1)> IO.puts(["StringA", " ", "StringB"])
StringA StringB
:ok
由于您将这些字符串作为变量放在某处,通过使用深层列表,您可以避免分配一个全新的字符串,只是为了将其输出到别处。 elixir / erlang中的许多函数都理解iolists,因此您通常不需要做额外的工作。
答案 2 :(得分:9)
为了完整性,您还可以使用字符串插值:
iex(1)> [a, b] = ["StringA", "StringB"]
iex(2)> "#{a} #{b}"
"StringA StringB"
答案 3 :(得分:5)
Enum.reduce对你的例子也有用吗?
iex(4)> Enum.reduce(["StringA", "StringB"], fn(x, acc) -> x <> " " <> acc end)
"StringB StringA"
答案 4 :(得分:4)
有很多方法,但是了解它如何处理nil值可以确定您应该选择哪种方法。
这将引发错误
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)
这只会插入一个空白的“”字符串:
iex(1)> "my name is #{nil}"
"my name is "
这将会:
iex(3)> Enum.join(["my name is", nil], " ")
"my name is "
还要考虑类型。使用<>
,您将无法获得任何免费转换:
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"
实践中的表现大致相同:
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}
因此,实际上取决于插入值是nil
还是类型错误时是否要崩溃。
答案 5 :(得分:3)
如果您可以在列表中添加空格,则可以将其视为iolist:
["StringA", " ", "StringB"] |> IO.iodata_to_binary # "StringA StringB"
这会给你一些性能提升,因为你没有复制内存中的任何字符串。
答案 6 :(得分:3)
这取决于您要执行的操作。如果您只是想写出一个新变量,请使用以下任一方法:
字符串插值
a = "StringA"
b = "StringB"
"#{a} #{b}"
字符串连接:"StringA" <> " " <> "StringB
Enum.join()
:["StringA", "StringB"] |> Enum.join(" ")
但是,正如Uri所提到的,也可以使用IOLists:
["StringA", " ", "StringB"] |> IO.iodata_to_binary
IOList实际上将是性能最高的。 Big Nerd Ranch拥有a good write-up的IOLists性能提升。
答案 7 :(得分:0)
你也可以'string A' ++ ' ' ++ 'string B'
答案 8 :(得分:0)
考虑使用IO列表,如果您具有[“ String1”,“ string2”]并在其上使用iolist_to_binary / 1,则将这些字符串复制到新字符串中。如果您有IO列表,则在大多数情况下可以将其输出,并将其连接在端口上。这是关键,运行时不需要复制数据,因此它比串联更有效。