【问题标题】:How can I merge a finite number of infinite lists in Haskell?如何在 Haskell 中合并有限数量的无限列表?
【发布时间】:2014-11-26 19:13:54
【问题描述】:

对于一个作业,我需要编写一些 Haskell 代码,该代码输入一个有限列表,该列表由无限的整数列表组成,每个列表单调递增。

现在,我需要将它们合并到一个对整数进行排序的列表中。此外,一些整数可能出现在多个列表中:在输出列表中,每个整数可能只出现一次。

所以如果输入例如 [ [1, 2, 6, 10, 28, 40, ...] [3, 4, 10, 28, 100, ...] , [任意数量的列表] ] 那么输出应该是 [1, 2, 3, 4, 6, 10, 28, 40, 100, ...]

我有点卡在这里。我不知道如何有效地使用foldr 来合并列表。我认为我应该比较每个列表的头部,然后从中创建一个新列表。

【问题讨论】:

  • 对无限列表进行排序通常不是很容易。如果我有输入 [[1, 3, 4, 5, 6, ...], [1, 3, 5, 7, ..]],然后我开始对它们进行排序以得到 [1, 3, 4, 5, 6, 7, ...],我怎么知道这两个输入列表中的某处没有出现 2?
  • 这是不可能的,除非您知道列表是单调递增的,我猜这在作业中有所说明。您能否确认并向我们展示您的尝试?如果您不只是说“告诉我如何”,那么这里的人通常会更有帮助。
  • 你不需要排序这些列表,你需要合并它们。它们必须已经排序。您不能对无限列表进行排序。
  • 我确实说错了。列表单调递增。所以确实需要合并。
  • 您是否考虑过如何合并两个列表?

标签: list haskell functional-programming


【解决方案1】:

您可以通过考虑合并两个无限排序列表来稍微简化问题,然后尝试泛化。该合并的骨架将如下所示:

mergeSorted :: Ord a => [a] -> [a] -> [a]
mergeSorted [] ys = ys
mergeSorted xs [] = xs
mergeSorted (x:xs) (y:ys) = ???

您必须比较 x 和 y,并做一些明智的事情,可能涉及对 mergeSorted 的递归调用:这看起来还不错,对吧?

现在,让我们假设 mergeSorted 有效,您可以将两个无限排序的列表变成一个无限排序的列表。如何将 N 个无限排序列表转换为单个排序列表?为什么,这是一个简单的折叠!只需将两个列表合并在一起,然后将第三个列表与那个列表合并,再将第四个列表与那个列表合并,以此类推。

mergeAll :: Ord a => [[a]] -> [a]
mergeAll xss = foldr ???

【讨论】:

  • 我会咬人的,我看不出你将如何使用折叠器解决 [[1],[7], [3], [2]] 的合并问题
  • @mhitza(注意 OP,您可能会认为这是一个剧透):简单。 mergeAll = foldr mergeSorted []; mergeAll [[1],[7], [3], [2]] 然后按预期计算为 [1,2,3,7]
  • @Will Ness,在这种情况下,最简洁的答案是使用来自 Data.List.Ordered 的 unionAll,这正是 OP 正在寻找的。 Ganesh,不要看 unionAll 的来源,除非你不介意完全剧透。一般来说,Data.List.Ordered 包括对有序列表进行操作的函数。
  • @fgv 我希望它使用标准 HOF(折叠/展开/直到)完成,正如 OP 提到的“使用 foldr”。
  • mergeAll,而不是 unionAll,解决了这里发布的问题。编辑:哇等等,我一直错过了问题中的一句话!我想这是联合,而不是合并。幸好我的骨架功能还可以。
【解决方案2】:

我们可以通过unfoldr pullunfoldrData.List),与

pull (x:xs,y:ys) | x<y = Just (x, (xs,y:ys))
                 | x>y = Just (y, (x:xs,ys))
                 | x==y = Just (x, (xs, ys))  -- pull same from both (NB!)

我们可以成对处理任何有限列表,将其长度减半:

pairs f (x:y:t)  = f (x,y) : pairs f t
pairs _ t        = t

重复一个步骤直到满足条件,这是until的工作:

uniquelyMerge xs = ... (until (...) (pairs (unfoldr pull)) xs)
.....

不要忘记处理空列表的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 2017-02-28
    • 2017-09-28
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    相关资源
    最近更新 更多