使用列表推导生成潜在组合

时间:2019-06-16 07:09:22

标签: elixir

我需要生成一系列具有确定值的序列数据,以针对算法进行测试。数据样本数据看起来像["apple", "orange", "apple", nil, "pineapple", nil],每个零点都需要苹果,橙子和菠萝的每种组合,例如,在这种情况下,我需要一个列表列表

[
  ["apple", "orange", "apple", "apple", "pineapple", "apple"],
  ["apple", "orange", "apple", "orange", "pineapple", "apple"],
  ["apple", "orange", "apple", "pineapple", "pineapple", "apple"],
  ["apple", "orange", "apple", "apple", "pineapple", "orange"],
  ["apple", "orange", "apple", "orange", "pineapple", "orange"],
  ...
]

我目前正在尝试使用List Comprehensions进行递归方法,但是我们公司才刚刚开始使用Elixir,但我还不了解它们如何结合在一起。

我有一个称为generate_sample_data的方法,该方法需要一个数据列表和一个累加器(列表列表)。

  def generate_sample_data(list, valid_lists \\ []) do
    case Enum.find_index(list, fn(f) -> f == nil end) do
      nil -> [list | valid_lists]
      index -> 
        for x <- ["apple", "orange", "pineapple"] do
          list
          |> List.update_at(index, fn(_)-> x end)
          |> Enum.each(&generate_sample_data/2)
        end
    end
  end

但是我收到错误#Function<4.433245229/2 in SampleData.generate_sample_data/2> with arity 2 called with 1 argument ("apple")

我不知道如何正确地将这些组合从列表理解转换为列表列表。我尝试做的一切似乎都给我带来了一个不同的错误,但是我感觉自己有点接近。

1 个答案:

答案 0 :(得分:1)

在您的特定情况下,问题在这里:

|> Enum.each(&generate_sample_data/2)

这是尝试通过唯一的参数(来自管道的列表)调用generate_sample_data/2

此外,Enum.each/2在那里毫无意义,因为您基本上是在遍历上一步中创建的有效列表的元素。

另一个潜在的问题是您从未使用过的nil -> [list | acc]局部变量中的acc子句。


FWIW,这是产生初始列表的所有排列的宏:

defmacro permutations(l, n) do
  clause = fn i -> {:<-, [], [{:"i#{i}", [], Elixir}, l]} end
  return = Enum.map (1..n, fn i -> {:"i#{i}", [], Elixir} end)
  Enum.reduce(1..n, return, fn i, acc ->
    {:for, [], [clause.(i), [do: acc]]}
  end)
end