在Elixir中构建长字符串的最佳方法是什么?

Mat*_*att 4 elixir

我想构建一个相对较长的字符串(如果重要的话是SVG)并从函数返回它.在Elixir中构建这样一个字符串的最佳方法是什么?在其他语言中,我会使用类似StringBuilder类的东西.Elixir中有相同的东西吗?

您可以使用<>运算符追加字符串,但这不仅仅是一个列表追加吗?似乎做了很多这样的事情会变得非常低效.

Dog*_*ert 7

Elixir Strings(在Erlang中称为Binaries)表示为内存中连续的字节序列,而不是字节/字符的链接列表,如果这就是"list"的含义.他们不可变的,一个天真的实施追加2个二进制文件将成为O(n+m)如果字符串的长度nm,但二郎山VM优化建设一个大型的字符串的使用情况:如果你有两个字符串,ab,并a有其分配后可用内存,并且你连接它们(a <> b),VM只复制b并重用旧的值a.如果以后串联另一个字符串这个原因很明显优化将不会应用ca,但这种优化本身就足以使建设一个大型二进制一样有效,与可变字符串语言的任务.这里详细解释了这种优化.

以下是此优化的演示实例.在第一个例子中,我通过附加到基值来创建10,000,000字节的字符串.在第二个例子中,我通过在基值之前创建一个500,000字节的字符串,这比追加10,000,000字节花费的时间多10倍.在一个天真的实现中,两者都需要相同的时间.

{time, _} = :timer.tc(fn ->
  Enum.reduce(1..10_000_000, "", fn _, acc -> acc <> "." end)
end)

IO.inspect time

{time, _} = :timer.tc(fn ->
  Enum.reduce(1..500_000, "", fn _, acc -> "." <> acc end)
end)

IO.inspect time
Run Code Online (Sandbox Code Playgroud)
683621
7807815
Run Code Online (Sandbox Code Playgroud)

简而言之,只要你只是附加值,你就可以很好地构建大字符串.


如果您要将结果字符串写入套接字或流或类似字符串,则可以通过创建iolists而不是平面字符串来显着提高它.关于这些更多信息在这里这里.