将列表拆分为指定索引处的列表元组

时间:2014-10-30 10:58:26

标签: list haskell

我在一个问题上找到了这段代码,这个问题类似于我试图解决的问题,并且我试图将此函数的逻辑应用于我的问题。但是,代码的解释在这个问题上并不完全清楚。代码如下:

   splitAtIndex :: Int -> [a] -> ([a], [a])
   splitAtIndex 0 xs    = ([], xs)
   splitAtIndex _ [] = ([], [])  
   splitAtIndex x (y:ys) =  (y:ys', ys'') 
     where 
       (ys', ys'') = splitAtIndex (x - 1) ys

我理解这一点的方法是,你获取索引和整个列表并形成一个列表元组,其中列表的元组等于列表尾部的索引-1的递归调用。我在这里错过了什么吗?撇号的使用在这里很重要吗?我真的不知道列表的拆分发生在哪里。我确信一旦解释它看起来很简单,但我似乎无法掌握它。

谢谢!

2 个答案:

答案 0 :(得分:1)

正如已经指出的那样,撇号相当于名字中的字母。惯例是,如果您有一个变量x,那么修改后的x副本通常称为x'

为消除这种混淆,您可以将定义重写为:

splitAtIndex x (y:ys) = (y:p, q) where (p, q) = splitAtIndex (x - 1) ys

要理解算法,考虑一个例子可能会有所帮助。我们假设您要将列表[1,2,3,4,5,6]拆分为位置2.呼叫将是:

splitAtIndex 2 [1,2,3,4,5,6]

函数中的where子句产生以下表达式:

splitAtIndex 1 [2,3,4,5,6]

因为ys是尾部而(x-1)是(2-1)。该表达式的结果是元组(p,q)。但是原始表达式的结果将原始列表的第一个元素聚合到元组(y:p,q)的第一个元素上。因此splitAtIndex 2 [1,2,3,4,5,6]的结果是(1:p, q),其中psplitAtIndex 1 [2,3,4,5,6]的第一个元素,q是该元组的第二个元素。我们希望splitAtIndex 1 [2,3,4,5,6]返回([2],[3,4,5,6]),最终结果为(1:[2],[3,4,5,6])([1,2],[3,4,5,6])

答案 1 :(得分:0)

撇号属于用于递归调用splitAtIndex (x - 1) ys的变量。这是唯一的含义。

当你开始思考指数为1时,你可以理解代码。在这里你取出元组左边的空列表,并在列表的左边悬挂。等等。