从Haskell中的列表中删除共轭元组

时间:2016-12-07 20:13:07

标签: list haskell tuples

我有一个元组列表。每个元组也是一个元组。对于每个外部元组,我有一个共轭元组。我的意思是,如果我在列表中有(a,b),那么我也有(b,a)。我想要的是从列表中删除共轭元组。

在这里给我一个具体的例子:

[((1,2,1,0),(5,2,1,0)),((2,4,4,0),(2,5,4,0)),((2,5,4,0),(2,4,4,0)),((3,1,1,0),(3,3,2,0)),((3,3,2,0),(3,1,1,0)),((5,1,7,0),(8,1,7,0)),((5,2,1,0),(1,2,1,0)),((5,5,8,0),(8,5,8,0)),((5,6,6,0),(8,6,8,0)),((5,9,9,0),(8,9,9,0)),((6,3,5,0),(6,8,9,0)),((6,8,9,0),(6,3,5,0)),((7,7,6,0),(9,7,6,0)),((8,1,7,0),(5,1,7,0)),((8,5,8,0),(5,5,8,0)),((8,6,8,0),(5,6,6,0)),((8,9,9,0),(5,9,9,0)),((9,7,6,0),(7,7,6,0))]

去除共轭元组后的结果应为:

[((1,2,1,0),(5,2,1,0)),((2,4,4,0),(2,5,4,0)),((3,1,1,0),(3,3,2,0)),((5,1,7,0),(8,1,7,0)),((5,5,8,0),(8,5,8,0)),((5,6,6,0),(8,6,8,0)),((5,9,9,0),(8,9,9,0)),((6,3,5,0),(6,8,9,0)),((7,7,6,0),(9,7,6,0)),]

我已经尝试了几个小时没有成功。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:5)

首先,我们可以将类型概括为以下内容:

nubTuples :: Eq a => [(a,a)] -> [(a,a)]

然而,为了让事情变得更有效率,我们还要求Ord a实例。nub . sort为什么这会让事情变得更容易?因为现在我们可以将元组转换为有序的正规形式。然后我们可以简单地nubTuples [(2,1)] = [(2,1)]。以下实现实际上只是基于该表示进行排序和结算,因此[(1,2)]而非import Data.List (sortOn, nubBy) import Data.Tuple (swap) nubTuples :: Ord a => [(a,a)] -> [(a,a)] nubTuples = nubBy unorderedCompare . sortOn orderTuple where orderTuple (x,y) | x < y = (x,y) | otherwise = (y,x) unorderedCompare x y = x == y || swap x == y

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

请注意,这会更改顺序并删除重复项:

nubWith

至于更改订单,我们可以使用discrimination包中Data.Discrimination的{​​{1}}函数来解决此问题。然后我们的代码将成为以下内容:

 import Data.Discrimination (nubWith, Grouping)

 nubTuples :: (Ord a, Grouping a) => [(a,a)] -> [(a,a)]
 nubTuples = nubWith orderTuple
   where orderTuple (x,y)
           | x < y = (x,y)
           | otherwise = (y,x)

这不需要排序,保持订单完好无损并且最大程度上是懒惰的(这通常对性能非常重要)。它仍然会删除重复项。

您可以简单地为任何类型派生Grouping个实例,例如:

{-# LANGUAGE DeriveGeneric #-}
import Data.Discrimination
import GHC.Generics

data A = A deriving Generic
instance Grouping A

请注意,4元组没有Grouping的实例。这将是解决它的方法:

nubFourTuples :: (Grouping a, Ord a, Grouping b, Ord b,
                  Grouping c, Ord c, Grouping d, Ord d)
              => [((a,b,c,d),(a,b,c,d))] -> [((a,b,c,d),(a,b,c,d))]
nubFourTuples = (fmap . both) reassociate . nubTuples . (fmap . both) associate
   where associate (w,x,y,z) = ((w,x),(y,z))
         reassociate ((w,x),(y,z)) = (w,x,y,z)
         both f (x,y) = (f x, f y)

答案 1 :(得分:2)

&#34;元组的每个元素也是一个元组&#34;

removeConj xs = foldl f [] xs
  where f b a = if (elem (snd a, fst a) b) then b else (a:b)