【问题标题】:Haskell - spliting a list into several listsHaskell - 将列表拆分为多个列表
【发布时间】:2019-06-05 11:25:36
【问题描述】:

给定一个已排序的元组列表,返回一个包含元组列表的列表,其中每个元组列表都符合条件:

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

我得到的错误:

【问题讨论】:

  • 这是一道作业题吗?
  • @PeterHall 这真的重要吗?我发布了我试图解决问题的努力,这不像我只是想要实现而不首先尝试解决它
  • @PeterHall 回答你的问题,不,这不是家庭作业。
  • Official-ish guidelines on asking and answering (potential) homework questions.。确实,这并不重要;如果这是一个好问题,不管它的作业状态如何,它都是一个好问题。
  • @MichaelLitchard 不过,感谢您分享您投反对票的原因,而不仅仅是投反对票。

标签: list haskell fold


【解决方案1】:

[(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) 没有正确的类型作为[[(Integer, Integer)]] 的尾部。

我把修复留给你;希望这足以阐明错误的含义,以便您取得进展。

【讨论】:

  • 感谢您的回答,我已经投票赞成,但不会接受它作为答案,因为它是部分答案。
【解决方案2】:

请注意,当使用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 函数而不是使用匿名函数更具可读性,因为它需要将最右边的元素与空列表处理为:

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 时返回其第二个参数,因此在此示例中,返回[]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-25
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 2023-01-11
    • 1970-01-01
    • 2011-05-05
    相关资源
    最近更新 更多