繁体   English   中英

所有可能的子列表都是成对的

[英]All possible sublists as pairs haskell

有点不确定如何恰当地说这个,所以请耐心等待!

给定一个列表[1,2,3,4]我想要一个列表元组列表,如下所示:[([1],[2,3,4]),([1,2],[3,4] ]),([1,2,3],[4])]。

问题的B部分也是在子列表中获得所有可能的排序。 所以在第一个元组的情况下,我希望2 3 4按顺序243,324,432,423 ......

是的,我喜欢非决定论。

import Data.List (inits, tails, permutations)
import Control.Arrow (first, second)

parta :: [a] -> [([a], [a])]
parta [] = []
parta xs = init . tail $ zip (inits xs) (tails xs)

对于b部分,我不确定你是否想要[([1],[2,3,4]), ([1],[3,4,2]), ...][([1],[[2,3,4],[3,4,2],...]), ...] 如果是后者,那么

partb :: [a] -> [([a], [[a]])]
partb = map (second permutations) . parta

编辑:哦,但你想要前者。 在这种情况下

partb :: [a] -> [([a], [a])]
partb = map (uncurry zip . first repeat . second permutations) . parta

最后编辑:因为我已经使用了Control.Arrow中的一些函数,我会注意到zip (inits xs) (tails xs)也可以写成(inits &&& tails) xs ,但我不确定这样更清楚。

A部分:使用非决定论monad! (列表monad)

第1步 :找到一个合适的方法将列表拆分为两个列表的元组。

Hoogling [a] -> ([a], [a])我们发现splitAt :: Int -> [a] -> ([a],[a])

import Data.List (splitAt, permutations) -- we'll need to permute for part B

第2步 :将其写入一个索引。

splitPair xs = splitAt 1 xs

第3步 :使其对许多索引不确定地工作。

splitPairs xs = do index <- [1..length xs-1]
                   return $ splitAt index xs

看看单选功能如何轻松转换为非确定性选择功能? (这与列表理解一样容易编写:)

splitPairs' xs = [splitAt i xs | i <- [1..length xs-1]]

B部分:使用非确定性monad更多!

splitPairsPerms xs = do (ys, zs) <- splitPairs xs
                        ys' <- permutations ys
                        zs' <- permutations zs
                        return $ (ys', zs')

进一步的想法

列表monad非常适合编写简单函数并将它们转换为非确定性函数。 然而,这种方法并不总是最有效的。 在我的例子中,我使用了length xssplitAt i xs ,它们必须遍历列表的长度才能执行它们的任务(好吧, splitAt只需要遍历索引i,这平均是索引i的一半长度。列表,如此相同的数量级)。 如果性能很重要,那么转换为序列可能是明智之举。

在第一种情况下,您只需将列表拆分为两个。 第一个将包含输入,第二个将最初为空。 然后从第一个元素中取出一个元素,并将其放在第二个元素中,直到第一个元素为空。

magic x = magic' x []
    where 
        magic' [] y = [[[], y]]
        magic' (x:xs) y = [[reverse y, (x:xs)]] ++ magic' xs (x:y)

接下来的问题是:它只是元素的简单排列。

perm x = perm' x [] []
    where
        perm' [] [] prefix = [prefix]
        perm' [] rest prefix = []
        perm' (x:xs) rest prefix =
            perm' (xs++rest) [] (x:prefix) ++
            perm' xs (x:rest) prefix

我最喜欢Dan的答案,因为我认为这是最有启发性的。 但是,如果你担心splitPair的效率,那么我认为这个相当直接的定义工作正常:

splitPair :: [a] -> [([a],[a])]
splitPair []       = ([],[]) : []
splitPair a@(x:xs) = ([],a)  : map (\(u,v)->(x:u,v)) (splitPair xs)

此定义与原始问题陈述略有不同,因为它返回第一个或最后一个列表为空的对。 这与大多数列表函数(如tailsinits的定义更为一致:

> splitPair [1,2,3,4]
[([],[1,2,3,4]),([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4]),([1,2,3,4],[])]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM