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

时间:2016-05-06 15:55:00

标签: haskell lambda

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

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

例如:

> split [1,2,3,4]

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

我离解决方案很远。任何人都可以帮助我吗?

4 个答案:

答案 0 :(得分:9)

以下是使用initstails的另一种方法:

设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)

答案 1 :(得分:2)

如果您想自己使用库函数 来实现它

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

答案 2 :(得分:1)

当然,使用splitAtflipimport Data.List很容易。

首先做let split x = map (flip splitAt x) [1..length x-1]

split [1,2,3,4]
[([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4])]

结果:

map

翻转说明 - 我们在此示例中使用flip[splitAt 1 x, splitAt 2 x, splitAt 3 x] 生成结果

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

Flip只是允许我们翻转预期的参数。否则我们可以像这样写一个lambda:

@section Scripts
{
   <script src="~/Scripts/YourAngularControllerFileForThisPage.js"></script>
   <script>
        var myApp = myApp || {};
        myApp.Settings = myApp.Settings || {};
        myApp.Settings.Url= "@Url.Action("VerifyLogin","Visitor")";
        angular.module("app").value("appSettings", myApp);
   </script>
}

答案 3 :(得分:1)

迭代的另一种方法

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