我正在学习Elixir,发现自己必须将多个列表连在一起,我有一个开头,中间和结尾。简化示例:
a = [1,2]
b = [3,4]
c = [5,6]
a ++ b ++ c
> [1, 2, 3, 4, 5, 6]
我在流中做了数千次,并想成为Elixirific。
我写了一个处理这个问题的函数,可能有些东西可以帮到我,但是我没有看到它。我应该使用内置的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]))
我将这些部件称为一起的顺序是否重要?
Way 1:
[1, 2]
|> append([3, 4])
|> append([5, 6])
...
Way 2:
end = append([3, 4], [5, 6])
append([1, 2], end)
中间列表是否会在两种情况下重复使用,因为它们都附加了标题指针?
对此的任何帮助都会很棒,欢呼。
答案 0 :(得分:10)
无论您使用什么方法,最终都会克隆除最后一个之外的所有列表,因为您无法在不克隆链接的情况下附加到链接列表。因此,如果您知道要连接列表(即您无法修改代码以接受[a, b, c]
等嵌套列表),我建议a ++ b ++ c
,因为++
已在Erlang&#39中实现; s代码,应该尽可能快,并且绝对比手动连接Enum.reverse/1
和Enum.reduce/3
更快。
这是一个比较a ++ b ++ c
与a |> 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