从元组列表中删除重复的键/值

时间:2016-04-10 09:37:53

标签: list haskell key tuples

我有一个元组列表,input: [("r","w"),("n","j"),("a","j"),("d","i"),("s","g"),("r","a")] output: [("r","w"),("n","j"),("d","i"),("s","g")] 对。我需要删除复制键或值的元素,列表的顺序可以更改,但键的第一次出现或值必须保留在元组列表中:

示例:

removeDuplicates  _   []  = []
removeDuplicates seen (x:xs) 
                        | elem (head $ fst x) (fst seen) = [] ++ removeDuplicates seen xs
                        | elem (head $ snd x) (snd seen) = [] ++ removeDuplicates seen xs
                        | otherwise  = x:removeDuplicates ((fst seen)++(fst x),(snd seen)++(snd x)) xs

我做了什么:

removeDuplicates ("","") something

但这需要被称为self.addEventListener('notificationclick', function(event) { console.log('Notification click: tag ', event.notification.tag); event.notification.close(); var url = 'https://youtu.be/gYMkEMCHtJ4'; event.waitUntil( clients.matchAll({ type: 'window' }) .then(function(windowClients) { for (var i = 0; i < windowClients.length; i++) { var client = windowClients[i]; if (client.url === url && 'focus' in client) { return client.focus(); } } if (clients.openWindow) { return clients.openWindow(url); } }) ); }); ,这很丑陋。

3 个答案:

答案 0 :(得分:4)

您可以使用Data.List包中的nubBy函数和相应的比较器:

removeDuplicates xs = nubBy cmpKeyAndVal xs 
  where
    cmpKeyAndVal (x, y) (x', y') = x == x' || y == y'

用作:

> removeDuplicates [("r","w"),("n","j"),("a","j"),("d","i"),("s","g"),("r","a")]
[("r","w"),("n","j"),("d","i"),("s","g")]

另请注意,当密钥或值为("", "")时,使用""调用您的实现会产生错误的结果。选择正确的第一个参数的唯一方法是放置一些没有出现在输入中的东西,这有点烦人。

请注意,上述实现需要O(n ^ 2)时间,这对Eq个实例来说是最佳的。如果您允许Ord约束,则可以使用实现稳定排序算法的sortBy函数,然后使用groupBy删除连续的重复项:< / p>

import Data.List(sortBy, groupBy)
import Data.Ord(comparing)
import Data.Function(on)

removeDuplicates xs = sortAndGroupBy snd (sortAndGroupBy fst xs)
  where
    sortAndGroupBy f = map head . groupBy ((==) `on` f). sortBy (comparing f)

这需要O(nlog n)时间,但显然需要Ord约束。

答案 1 :(得分:0)

首先,养成在编写函数时添加类型签名的习惯。它让你保持理智和诚实,它可以捕捉你想要做的事情,并且在你实现你的功能之前最好写出来。

removeDuplicates :: (Eq a, Eq a1) => ([a], [a1]) -> [([a], [a1])] -> [([a], [a1])]

如果你想在没有附加参数的情况下调用它,我建议这样:

remove :: (Eq a, Eq a1) => [([a], [a1])] -> [([a], [a1])]
remove = removeDuplicates ("","")

另一个更通用的版本不能仅使用列表作为元组的元素,将是这样的:

removeX :: (Eq t, Eq s) => [(t, s)] -> [(t, s)]
removeX [] = []
removeX (xx@(x,y):xs) = let xs' = filter (\(a,b) -> not (a == x || b ==y) ) xs
                        in xx:removeX xs'

如果您想坚持标准功能 - @Bakuriu为您提供正确的答案

答案 2 :(得分:0)

将累加器放在辅助函数中。

removeDuplicates lst = rd lst []
                       where rd _ [] = []
                             rd seen (x:xs) = ...