我有三个列表。我们先说吧 [a,b,c],[d,e]和[f,g,h] 现在我想产生所有可能性。结果始终是以下语法: list1 + elem list2 + elem list3
中的元素例如: ADF AEG CDF BDF bdg
等等。
目前我不知道。我想使用类似for-each-loop的东西,但它确实在haskell中工作^^你有解决这个问题的一些问题吗?
谢谢!
答案 0 :(得分:9)
一种方法是使用列表推导,如user2407038建议
allCombinations1 xs ys zs = [(x, y, z) | x <- xs, y <- ys, z <- zs]
同样地,这个列表理解涉及到monadic代码
allCombinations2 xs ys zs = do
x <- xs
y <- ys
z <- zs
return (x, y, z)
这相当于使用liftM3
中的Control.Monad
:
allCombinations3 = liftM3 (\x y z -> (x, y, z))
您还可以使用forM
和concat
以命令式方式执行相同的操作:
allCombinations4 xs ys zs = concat . concat . concat $
forM xs $ \x ->
forM ys $ \y ->
forM zs $ \z ->
return (x, y, z)
但这可能更慢,并且当然不是惯用的Haskell代码。或者,您也可以将sequence
用于任意数量的输入,这当然是最通用和最短的输入:
allCombinations5 :: [[a]] -> [[a]]
allCombinations5 = sequence
测试它们:
> allCombinations1 [1, 2] [3, 4] [5, 6]
[(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)]
> allCombinations2 [1, 2] [3, 4] [5, 6]
[(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)]
> allCombinations3 [1, 2] [3, 4] [5, 6]
[(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)]
> allCombinations4 [1, 2] [3, 4] [5, 6]
[(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)]
> allCombinations5 [[1, 2], [3, 4], [5, 6]]
[[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6],[2,4,5],[2,4,6]]
请注意,最后一个不会返回元组列表而是返回列表列表,因为它可用于获取N个输入的差异组合,而不是固定数量的输入。
像Haskell中的大多数事情一样,这个问题可以通过多种方式解决,我确信甚至还有其他方法可以添加到此列表中。就个人而言,如果您想要任意数量的输入,我建议使用sequence
,否则建议使用列表理解形式。对于其他Haskellers来说,两者都是非常易读和易懂的