在Elixir

时间:2017-01-24 06:17:06

标签: elixir

我正在学习Elixir,发现自己必须将多个列表连在一起,我有一个开头,中间和结尾。简化示例:

a = [1,2]
b = [3,4]
c = [5,6]
a ++ b ++ c
> [1, 2, 3, 4, 5, 6]

我在流中做了数千次,并想成为Elixirific。

第1部分)

我写了一个处理这个问题的函数,可能有些东西可以帮到我,但是我没有看到它。我应该使用内置的Elixir功能吗?

def append(front, back) when is_list(front) when is_list(back) do
  front
  |> Enum.reverse
  |> Enum.reduce(back, &([&1 | &2]))
end

或者我应该这样做,随着时间的推移对我来说会更自然吗?

[1, 2]
|> Enum.reverse 
|> Enum.reduce([3, 4], &([&1 | &2]))
|> Enum.reverse
|> Enum.reduce([5, 6], &([&1 | &2]))

第2部分)

我将这些部件称为一起的顺序是否重要?

Way 1:
[1, 2]
|> append([3, 4])
|> append([5, 6])

...
Way 2:
end = append([3, 4], [5, 6])
append([1, 2], end)

中间列表是否会在两种情况下重复使用,因为它们都附加了标题指针?

对此的任何帮助都会很棒,欢呼。

1 个答案:

答案 0 :(得分:10)

无论您使用什么方法,最终都会克隆除最后一个之外的所有列表,因为您无法在不克隆链接的情况下附加到链接列表。因此,如果您知道要连接列表(即您无法修改代码以接受[a, b, c]等嵌套列表),我建议a ++ b ++ c,因为++已在Erlang&#39中实现; s代码,应该尽可能快,并且绝对比手动连接Enum.reverse/1Enum.reduce/3更快。

这是一个比较a ++ b ++ ca |> append(b) |> append(c)的微小基准标记:

defmodule BasicBench do
  use Benchfella

  bench "++", [a: gen(), b: gen(), c: gen()] do
    a ++ b ++ c
  end

  bench "append", [a: gen(), b: gen(), c: gen()] do
    a |> append(b) |> append(c)
  end

  def append(front, back) when is_list(front) when is_list(back) do
    front
    |> Enum.reverse
    |> Enum.reduce(back, &([&1 | &2]))
  end

  def gen, do: Enum.to_list(1..1000)
end

和输出:

benchma iterations   average time
++          100000   10.22 µs/op
append       20000   75.79 µs/op