Elixir函数生成惰性列表理解

时间:2017-06-25 19:35:33

标签: elixir

使用已知数量的流与此答案相关:https://stackoverflow.com/a/32436384/1578888

如何构建一个create_stream函数,以类似的方式嵌套任意数量的流,即:

create_stream([1..1_000_000, 1..5_000_000]) 

#should be equivalent to:
Stream.flat_map 1..1_000_000, fn i ->
  Stream.flat_map 1..5_000_000, fn j ->
    [{i, j}]
  end
end

create_stream([1..1_000_000, 1..5_000_000, 1..10_000_000]) 

#should be equivalent to:
Stream.flat_map 1..1_000_000, fn i ->
  Stream.flat_map 1..5_000_000, fn j ->
    Stream.flat_map 1..10_000_000, fn k ->
      [{i, j, k}]
    end
  end
end

1 个答案:

答案 0 :(得分:0)

这很可能不如手动嵌套Stream.flat_map/2那么有效,但它可以使用任意数量的流:

defmodule MyStream do
  def combine(list), do: combine(list, [])

  defp combine([h], acc) do
    Stream.map(h, fn x ->
      [x | acc] |> Enum.reverse |> List.to_tuple
    end)
  end
  defp combine([h | t], acc) do
    Stream.flat_map(h, fn x ->
      combine(t, [x | acc])
    end)
  end
end

expected = for a <- 1..2, b <- 3..4, c <- 5..6, d <- 7..8, do: {a, b, c, d}
actual = [1..2, 3..4, 5..6, 7..8] |> MyStream.combine |> Enum.to_list |> IO.inspect
IO.inspect actual == expected

输出:

[{1, 3, 5, 7}, {1, 3, 5, 8}, {1, 3, 6, 7}, {1, 3, 6, 8}, {1, 4, 5, 7},
 {1, 4, 5, 8}, {1, 4, 6, 7}, {1, 4, 6, 8}, {2, 3, 5, 7}, {2, 3, 5, 8},
 {2, 3, 6, 7}, {2, 3, 6, 8}, {2, 4, 5, 7}, {2, 4, 5, 8}, {2, 4, 6, 7},
 {2, 4, 6, 8}]
true