是否有标准的Elixir函数可以在列表的每个第n个索引处插入一个元素?
使用函数调用并返回如下:
iex> List.insert_at_every([1,2,3,4,5], 2, Enum.random(["apple","banana"]))
[1, 2, "apple", 3, 4, "apple", 5]
答案 0 :(得分:2)
据我所知,目前还没有内置功能,但可以使用Enum.with_index
和Enum.flat_map
来完成。当索引的剩余部分和第二个参数是第二个参数减去1时,我们将元素+回调插入到结果列表中,否则只插入元素。我认为将1
作为每个参数传递给您的示例列表而不是2
更有意义。如果您愿意,可以随every
更改every - 1
。
defmodule A do
def insert_at_every(list, every, fun) do
list
|> Enum.with_index
|> Enum.flat_map(fn {x, i} ->
if rem(i, every) == every - 1 do
[x, fun.()]
else
[x]
end
end)
end
end
IO.inspect A.insert_at_every([1, 2, 3, 4, 5], 1, fn -> Enum.random(["apple", "banana"]) end)
IO.inspect A.insert_at_every([1, 2, 3, 4, 5], 2, fn -> Enum.random(["apple", "banana"]) end)
IO.inspect A.insert_at_every([1, 2, 3, 4, 5], 3, fn -> Enum.random(["apple", "banana"]) end)
输出:
[1, "apple", 2, "apple", 3, "banana", 4, "banana", 5, "apple"]
[1, 2, "apple", 3, 4, "apple", 5]
[1, 2, 3, "apple", 4, 5]
答案 1 :(得分:2)
NB @Dogbert提出的解决方案无论如何都更好,我为了多样性而发布这个。
要使用常量值散布列表,可以使用Enum.chunk_every/2
和Enum.intersperse/2
:
iex(1)> [1,2,3,4,5]
...(1)> |> Enum.chunk_every(2)
...(1)> |> Enum.intersperse("banana")
...(1)> |> List.flatten
#⇒ [1, 2, "banana", 3, 4, "banana", 5]
如果要在每次迭代时使用函数检索要散布的元素,则无效。在这种情况下,你要自己实现散布:
iex(2)> [1,2,3,4,5]
...(2)> |> Enum.chunk_every(2)
...(2)> |> Enum.map(& &1 ++ [Enum.random(~w|banana apple|)])
...(2)> |> List.flatten
#⇒ [1, 2, "banana", 3, 4, "apple", 5, "apple"]
上面的结果总是包含一个冗余的尾随元素,之后应该删掉它:
iex(3) > with [_ | result] <- :lists.reverse([1, 2, "banana", 3, 4, "apple", 5, "apple"]) do
...(3)> :lists.reverse(result)
...(3)> end
#⇒ [1, 2, "banana", 3, 4, "banana", 5]