【问题标题】:Elixir function to generate lazy list comprehensionElixir 函数生成惰性列表理解
【发布时间】:2017-06-26 03:43:08
【问题描述】:

使用已知数量的流与此答案相关:https://*.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

【问题讨论】:

    标签: elixir


    【解决方案1】:

    这很可能不如手动嵌套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
    

    【讨论】: