给出一个已排序的元组列表,返回一个包含元组列表的列表,其中每个元组列表都符合条件:
1)对于元组列表中的每个(a,b)和(c,d),a == c
2)每个元组的第二个元素必须是前一个+1,因此对于[(a,y1),(b,y2),(c,y3)] => y2 = y1 + 1; y3 = y2 +1
示例:
输入
ex = [(0,2),(1,0),(1,2),(1,3),(1,4),(2,4)]
输出
groupTogether ex = [[(0,2)],[(1,0)],[(1,2),(1,3),(1,4)],[(2,4)] ]
这必须使用折叠来实现。
我的实现:
groupTogether :: [(Integer,Integer)]-> [[(Integer,Integer)]]
groupTogether [] = []
groupTogether pairs@(x:xs) = foldr (\(a,b) acc -> if ( (a == fst(last(last(acc)))) && (b == fst(last(last(acc)))) )
then (a,b) : (last(last(acc)))
else [(a,b)] : ((last(acc)))
) [[]] pairs
我得到的错误:
答案 0 :(得分:3)
在
[(a,b)] : last acc
我们有:
acc :: [[(Integer, Integer)]] -- presumed
last acc :: [(Integer, Integer)]
[(a,b)] :: [(Integer, Integer)]
因此,[(a,b)]
具有正确的类型作为[[(Integer, Integer)]]
的第一个元素,但是last acc
没有正确的类型作为[[(Integer, Integer)]]
的尾部。
在
(a,b) : last (last acc)
我们有:
acc :: [[(Integer, Integer)]] -- presumed
last acc :: [(Integer, Integer)]
last (last acc) :: (Integer, Integer)
(a,b) :: (Integer, Integer)
因此,(a,b)
没有正确的类型成为[[(Integer, Integer)]]
的第一个元素,而last (last acc)
没有正确的类型成为{{1}的尾部}。
我将解决方法留给您;希望这足以阐明错误的含义,以便您可以取得进步。
答案 1 :(得分:3)
请注意,使用foldr
时,将首先处理给定列表的右侧元素。例如,列表:
[(0,2),(1,0),(1,2),(1,3),(1,4),(2,4)]
在处理第三个元素(1,2)
时,处理后的元素即acc
acc = [[(1,3),(1,4)],[(2,4)]]
因此,需要与(1,2)
比较的元素是(1,3)
。即head (head acc)
而非last (last acc)
。而且,除了使用head
之外,还可以通过以下模式匹配来访问它:
(pairs@((x, y):xs):xss)
并与(a, b)
进行比较:
a == x && b == (y - 1)
并在满足条件的情况下将它们分组在一起:
((a, b):pairs):xss
此外,定义阶跃函数而不是使用匿名函数更容易理解,因为它需要使用空白列表来处理最右边的元素,
step p [] = [[p]]
第一个元素一旦处理完毕,acc = [[p]]
就不会在后续步骤中成为空列表,因此与上面定义的模式匹配。这是定义阶跃函数的方法:
groupTogether = foldr step []
where step p [] = [[p]]
step p@(a, b) acc@(pairs@((x, y):xs):xss)
| a == x && b == (y - 1) = (p:pairs):xss
| otherwise = [p]:acc
了解foldr
的工作原理时,步进功能很简单。最后,作为补充说明,进行声明:
groupTogether [] = []
不是必需的。由于foldr
在将空白列表传递给groupTogether
时将返回其第二个参数,因此在此示例中,返回[]
。