我有一个给定的列表,例如[2, 3, 5, 587]
我希望有一个完整的组合列表。所以想要[2, 2*3,2*5, 2*587, 3, 3*5, 3*587, 5, 5*587, 587]
之类的东西。由于我在初学者级别与Haskell,我很好奇列表操作将如何。
此外,我很好奇如果基本列表的计算可能很昂贵,这将如何影响功能的成本? (如果我会认为列表有限制值,即<20)
Rem:列表的顺序可以在之后完成,但我真的不知道如果在函数内或之后更便宜。
答案 0 :(得分:6)
其他人已经解释了如何配对,所以我在这里关注自己的组合。
如果您想要所有长度的组合,那只是列表的power set,可以通过以下方式计算:
powerset :: [a] -> [[a]]
powerset (x:xs) = let xs' = powerset xs in xs' ++ map (x:) xs'
powerset [] = [[]]
-- powerset [1, 2] === [[],[2],[1],[1,2]]
-- you can take the products:
-- map product $ powerset [1, 2] == [1, 2, 1, 2]
在Haskell中有一个替代的powerset
实现,它被认为是一种经典:
import Control.Monad
powerset = filterM (const [True, False])
您可以查看filterM
的{{3}},了解它的工作方式与上面的其他powerset
基本相同。
另一方面,如果您想要拥有特定尺寸的所有组合,您可以执行以下操作:
combsOf :: Int -> [a] -> [[a]]
combsOf n _ | n < 1 = [[]]
combsOf n (x:xs) = combsOf n xs ++ map (x:) (combsOf (n - 1) xs)
combsOf _ _ = []
-- combsOf 2 [1, 2, 3] === [[2,3],[1,3],[1,2]]
答案 1 :(得分:2)
所以看起来你想要的是列表中的所有产品对:
ghci> :m +Data.List
ghci> [ a * b | a:bs <- tails [2, 3, 5, 587], b <- bs ]
[6,10,1174,15,1761,2935]
但你也想要初始数字:
ghci> [ a * b | a:bs <- tails [2, 3, 5, 587], b <- 1:bs ]
[2,6,10,1174,3,15,1761,5,2935,587]
这使用了列表解析,但这也可以通过常规列表操作来完成:
ghci> concatMap (\a:bs -> a : map (a*) bs) . init $ tails [2, 3, 5, 587]
[2,6,10,1174,3,15,1761,5,2935,587]
后者更容易解释:
Data.List.tails
生成列表的所有后缀:
ghci> tails [2, 3, 5, 587]
[[2,3,5,587],[3,5,587],[5,587],[587],[]]
Prelude.init
删除列表中的最后一个元素。在这里,我使用它来删除空后缀,因为处理会在下一步中导致错误。
ghci> init [[2,3,5,587],[3,5,587],[5,587],[587],[]]
[[2,3,5,587],[3,5,587],[5,587],[587]]
ghci> init $ tails [2, 3, 5, 587]
[[2,3,5,587],[3,5,587],[5,587],[587]]
Prelude.concatMap
在列表的每个元素上运行一个函数,并将结果合并到一个展平列表中。所以
ghci> concatMap (\a -> replicate a a) [1,2,3]
[1, 2, 2, 3, 3, 3]
\(a:bs) -> a : map (a*) bs
做了几件事。
init
删除了空列表)并将初始元素填入a
并且以后的元素到bs
。a:
具有相同的第一个元素,但a
(map (a*) bs
)。答案 2 :(得分:1)
您可以使用Data.List.tails
获取列表的后缀。
这将为您提供一个列表列表,然后您可以使用以下函数在此列表中执行所需的内部乘法:
prodAll [] = []
prodAll (h:t) = h:(map (* h) $ t)
然后,您可以在每个内部列表上映射此函数并连接结果:
f :: Num a => [a] -> [a]
f = concat . map prodAll . tails