2014-11-25 125 views
0

我有一个Haskell列表的列表。从每个列表中取一个元素时,我想获得所有可能性。我目前拥有的是从列表清单中清除列表理解?

a = [ [1,2], [10,20,30], [-1,-2] ] -- as an example 
whatIWant = [ [p,q,r] | p <- a!!0, q <- a!!1, r <- a!!2 ] 

这就是我想要的。然而,这显然不是很好的代码,而且我正在寻找更好的方式来编写列表理解,以便在代码中不显示索引号(0,1,2)...这就是我所在的位置卡住。

我该怎么做?

+2

你坚持使用列表理解来做它吗?我认为对于这样的任务来说,功能更好,更清洁。 – zegkljan 2014-11-25 10:15:53

+0

@JanŽegklitz感谢您的评论。这并不是说我坚持这样做:我只是觉得用一个列表理解来写一个好的,干净的方法,而且根本不知道这是否可行。 – Yosh 2014-11-25 10:19:13

+5

你想要所有列表的笛卡尔积。使用'序列a'来实现这一点。 http://stackoverflow.com/questions/3387359/calculate-n-ary-cartesian-product – chi 2014-11-25 10:27:44

回答

1

这显然不是一个好的代码

这是你能做到这一点的最好办法,因为你的约束输入是列表的列表。

如果您使用其他类型,例如列表的三倍,那么你可以在结构上进行索引。例如。

Prelude> let [email protected](a,b,c) = ([1,2], [10,20,30], [-1,-2]) 

让你写:

Prelude> [ (p,q,r) | p <- a , q <- b , r <- c ] 
[(1,10,-1),(1,10,-2),(1,20,-1) 
,(1,20,-2),(1,30,-1),(1,30,-2) 
,(2,10,-1),(2,10,-2),(2,20,-1) 
,(2,20,-2),(2,30,-1),(2,30,-2)] 

课:避免索引,使用类型,其结构捕捉你想要保持不变。将数据的维数提升到其类型。

+0

如果我必须处理大列表,那么该怎么办?(x @(a,b,c,....,z,za) 。))'?我是否应该像@JanŽegklitz所建议的那样寻求功能? //我只在模式匹配的情况下知道'@',这很好理解。 – Yosh 2014-11-25 10:20:56

2

使用功能(使用内部列表理解),我的解决办法是

combinations :: [[a]] -> [[a]] 
combinations [] = [] 
combinations [l] = map (\ x -> [x]) l 
combinations (x:xs) = combine (combinations [x]) (combinations xs) 
    where combine a b = [ p ++ q | p <- a, q <- b ] 

例子:

*Main> combinations [[1, 2, 3], [4, 5, 6]] 
[[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]] 
*Main> combinations [['a', 'b', 'c'], ['A', 'B', 'C'], ['1', '2']] 
["aA1","aA2","aB1","aB2","aC1","aC2","bA1","bA2","bB1",... 
"bB2","bC1","bC2","cA1","cA2","cB1","cB2","cC1","cC2"] 

编辑:当然你可以使用sequence功能,在评论中提出:

*Main> sequence [['a', 'b', 'c'], ['A', 'B', 'C'], ['1', '2']] 
["aA1","aA2","aB1","aB2","aC1","aC2","bA1","bA2","bB1",... 
"bB2","bC1","bC2","cA1","cA2","cB1","cB2","cC1","cC2"]