在Elixir中有效地压缩不等长的列表

时间:2019-05-12 05:37:14

标签: list zip elixir reduce enumeration

Elixir zip/2函数压缩两个列表,在到达较短列表的末尾时停止。我一直在尝试相反的做法-本质上是从较短的列表中复制项目,直到到达最长的列表的末尾。

这就是我所拥有的:

def zipReduce(m, n) when is_list(m) and is_list(n) do
  { long, short } = if length(m) > length(n)
    do { m, n }
    else { n, m }
  end

  Enum.reduce(0..Integer.mod(length(long), length(short)), [], fn i, acc ->
    long
    |> Enum.slice(length(short) * i, length(short))
    |> Enum.zip(short)
    |> Enum.into(acc)
  end)
end

它确实有效,但是我不喜欢所有对length/1的调用,因为每个调用都需要完整的列表遍历,并且这可能会减少很多。我可以将长度与短列表和长列表一起存储在元组中,但这感觉非常必要(尽管如果需要,我会这样做以提高性能)。

有没有想到的做到这一点的方法?可能是完全不同的方法吗?

1 个答案:

答案 0 :(得分:6)

执行以下操作:

Enum.zip(Stream.cycle(short), long)

例如

iex(1)> Enum.zip(Stream.cycle([1,2,3,4]), [:a, :b, :c, :d, :e, :f, :g, :h])
[{1, :a}, {2, :b}, {3, :c}, {4, :d}, {1, :e}, {2, :f}, {3, :g}, {4, :h}]

这将循环遍历较短列表中的元素,就像循环较长列表中的数据一样。