【问题标题】:Remove pair duplicates Haskell删除对重复的 Haskell
【发布时间】:2019-04-16 14:20:04
【问题描述】:

给出一个对的列表,例如

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

所以,我正在尝试删除重复的对,如果 (x, y) == (y, x),我认为一对重复,例如:(1, 2) 和 (3, 1)

我正在生成带有理解列表的列表,它来自一个列表

MyList = [(intA, intB) | x <- integerList, y <- integerList, x /= y]
integerList = [1, 2, 3];

请注意,我写的第一件事只是我想要发生的事情的一个例子,它不是上面理解列表的输出。

我最近开始使用 Haskell,我将如何解决这个问题?什么是最好的选择?我尝试使用地图,但没有成功,我应该将地图与在其中使用反向的 foldl / foldr 结合起来吗?我该怎么做?

【问题讨论】:

  • 错字? (1, 2) with (3, 1)
  • 先写isPairDuplicate :: (Int,Int) -&gt; (Int, Int) -&gt; Bool(然后将其发布在您的问题中,以便我们知道您在说什么)。
  • 那么我建议考虑编写一个在列表上使用模式匹配的递归解决方案,如果你感觉很疯狂,也许filter

标签: haskell


【解决方案1】:

现在是使用Hoogle 的最佳时机!让我们想想你在寻找什么。要删除重复项,我们需要一个列表 [a] 并从中删除一些东西,基于一些谓词 a -&gt; a -&gt; Bool 返回 [a]。这意味着我们正在寻找具有以下形式的函数:

ourFunction :: (a -> a -> Bool) -> [a] -> [a]

我们实际上可以使用函数签名(a -&gt; a -&gt; Bool) -&gt; [a] -&gt; [a] 搜索Hoogle,第一个结果是nubBy,这正是我们想要的!

话虽如此,您不需要使用它来解决您的问题。你已经在正确的轨道上。想想你在问什么——你不想要(x, y) == (y, x) 的重复元组。因此,只需选择您是否想要 y &lt; x 或其他方式,然后在您的列表理解中使用它:

> let fn xs = [(a, b) | a <- xs, b <- xs, a < b]
> fn [1, 2, 3]
[(1,2),(1,3),(2,3)]

如果您需要两个列表(一个有重复,一个没有),我建议使用两个单独的列表推导。它的性能较差,因为您编写的列表理解为 O(n^2),但在我看来,它更简洁、更容易学习。

【讨论】:

  • 这是一个不需要 Ord 实例的元素,并且不会通过生成错误的元素然后删除它们来做额外的工作:fn xs = [(a, b) | a:xs' &lt;- tails xs, b &lt;- xs']。我已经在实际代码中多次使用过这个标准技巧或它的轻微变体。当然它也有你的问题:如果输入列表有重复,输出也会有。
【解决方案2】:
import Data.List(nubBy)
import Data.Tuple(swap)

nubBy (\x y -> x==y || swap x == y) [(1, 2), (1, 3), (1, 4), (2, 1), (3, 1), (4, 1)]
[(1,2),(1,3),(1,4)]

或编写自己的版本

【讨论】:

  • 然而,最好在列表理解的源头解决问题。我根据标题和第一段描述回答了这个问题。
【解决方案3】:

它不是直接回答问题,但是有一个更简单的解决方案适用于这种情况(数字元组),只是在生成列表时添加一个过滤器以确保后一个元素始终大于前一个元素.

MyList = [(x, y)| x <- integerList, y <- integerList, x /= y, x < y]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 2011-06-06
    • 2011-02-16
    • 1970-01-01
    • 2013-04-13
    相关资源
    最近更新 更多