我需要一个与itertools.combinations(iterable, r)
in python
到目前为止,我提出了这个问题:
{-| forward application -}
x -: f = f x
infixl 0 -:
{-| combinations 2 "ABCD" = ["AB","AC","AD","BC","BD","CD"] -}
combinations :: Ord a => Int -> [a] -> [[a]]
combinations k l = (sequence . replicate k) l -: map sort -: sort -: nub
-: filter (\l -> (length . nub) l == length l)
是否有更优雅高效的解决方案?
答案 0 :(得分:7)
xs
n
n
个mapM (const xs) [1..n]
元素
allCombs xs = [1..] >>= \n -> mapM (const xs) [1..n]
所有组合(n = 1,2,...)
filter ((n==).length.nub)
如果你需要不重复
combinationsWRep xs n = filter ((n==).length.nub) $ mapM (const xs) [1..n]
然后
{{1}}
答案 1 :(得分:4)
(根据@JoseJuan的回答)
您还可以使用列表推导来过滤掉第二个字符并不严格小于第一个字符的列表:
[x| x <- mapM (const "ABCD") [1..2], head x < head (tail x) ]
答案 2 :(得分:4)
(根据@ FrankSchmitt的回答)
我们有map (const x) [1..n] == replicate n x
所以我们可以将答案改为
[x| x <- sequence (replicate 2 "ABCD"), head x < head (tail x) ]
虽然在原始问题中,2
是参数k
,但对于此特定示例,可能不希望使用2复制并写入
[ [x1,x2] | x1 <- "ABCD", x2 <- "ABCD", x1 < x2 ]
代替。
使用参数k
如果你想生成没有重复的东西,事情会有点棘手。我会递归地做:
f 0 _ = [[]]
f _ [] = []
f k as = [ x : xs | (x:as') <- tails as, xs <- f (k-1) as' ]
(如果列表中已有as
,则此变体不会删除重复项;如果您担心它们,请将nub as
传递给它
答案 3 :(得分:3)