Haskell 从列表中获取可变数量的元素

Haskell 从列表中获取可变数量的元素,haskell,lambda,Haskell,Lambda,我想创建一个函数,它返回将列表拆分为两个非空部分的所有可能方法的列表 split :: [([a], [a])] 例如: > split [1,2,3,4] > [ ([1], [2,3,4]), ([1,2], [3,4]), ([1,2,3], [4]) ] 我离解决方案还很远。有人能帮我吗?当然,使用地图、拆分和翻转很容易 首先要导入数据 结果: split [1,2,3,4] [([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4])] fl

我想创建一个函数,它返回将列表拆分为两个非空部分的所有可能方法的列表

split :: [([a], [a])]
例如:

> split [1,2,3,4]

> [ ([1], [2,3,4]), ([1,2], [3,4]), ([1,2,3], [4]) ]
我离解决方案还很远。有人能帮我吗?

当然,使用地图、拆分和翻转很容易

首先要导入数据

结果:

split [1,2,3,4]
[([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4])]
flip的解释-在本例中,我们使用map和flip生成结果

[splitAt 1 x, splitAt 2 x, splitAt 3 x]
Flip只允许我们翻转预期参数。否则我们就可以这样写一个lambda:

let split x = map (\z -> splitAt z x) [1..length x-1]

下面是使用inits和tails的另一种方法:

设xs=[1,2,3,4]。注:

import Data.List

inits xs -- returns: [[]       ,     [1], [1,2], [1,2,3], [1,2,3,4]]
tails xs -- returns: [[1,2,3,4], [2,3,4], [3,4], [4]    , []]
因此,将这两个列表压缩在一起可以提供将列表分为两部分的所有方法:

zip (inits xs) (tails xs)
  = [ ([], [1,2,3,4]),
      ([1], [2,3,4] ),
      ([1,2], [3,4]) ,
      ([1,2,3,4], []) ]
如果不需要第一对和最后一对,只需适当修剪:

split xs = init $ tail $ zip (inits xs) (tails xs)

如果您想自己实现它,而不是使用库函数

splits :: [a] -> [([a],[a])]
splits [] = []
splits xx = splits' ([],xx)
  where splits' :: ([a],[a]) -> [([a],[a])]
        splits' xy@(x,[]) = [xy]
        splits' xy@(x,y:yy) = let z = (x++[y],yy)
                              in xy:splits' z

迭代的另一种方法

split (x:xs) = takeWhile (not . null . snd) $ iterate (\(x,(y:ys)) -> (x++[y],ys)) ([x], xs)

谢谢!我没有想到这个快速的解决方案!再次感谢!您也可以使用中缀splitAt而不是flip splitAt x。最好提及对数据执行类似操作。序列非常节省时间和空间,感谢Louis Wasserman出色的inits和tails实现,并在较小程度上感谢我自己的zip/zip实现。@dfeuer为什么它惊人地节省时间和空间-我认为Data.Sequence非常适合解决此类问题。@epsilonhalbe,它的inits和tails继续给我留下深刻印象。
split (x:xs) = takeWhile (not . null . snd) $ iterate (\(x,(y:ys)) -> (x++[y],ys)) ([x], xs)