问题
I need a function that could be called uniqueBy
that would remove all elements in a list of tuples that have the same snd
value, without keeping even one of them as nubBy
would.
For example,
uniqueBy [(1,1),(2,1)]
should return []
, whereas
uniqueBy [(1,1),(1,1),(1,2)]
would return [(1,2)]
.
Sadly this function uniqueBy
does not exist and I can't seem to find an alternative function or a way to implement it myself, although I'm sure there has to be an easy way.
回答1:
The Data.List module has a nubBy :: (a -> a -> Bool) -> [a] -> [a] function. You thus can use this like:
import Data.Function(on)
import Data.List(nubBy)
uniqueOnSnd :: Eq b => [(a, b)] -> [(a, b)]
uniqueOnSnd = nubBy ((==) `on` snd)
For example:
Main> uniqueOnSnd [(4,1), (5,2), (3,1), (2,0)]
[(4,1),(5,2),(2,0)]
nubBy
takes, just like nub
, O(n2) time. So in case you can order the elements, it is more efficient to first order and then perform a uniqness filter, like:
import Data.Function(on)
import Data.List(sortBy)
nubOrderBy :: (a -> a -> Ordering) -> [a] -> [a]
nubOrderBy cmp = go . sortBy cmp
where go (x1:xs) = x1 : go (dropWhile ((EQ ==) . cmp x1) xs)
go [] = []
uniqueOnSnd :: Ord b => [(a, b)] -> [(a, b)]
uniqueOrdOnSnd = nubOrderBy (compare `on` snd)
A disadvantage of this is that it can not work with infinite lists, and furthermore that the order will not be preserved, but here w thus filter out duplicates in O(n log n).
来源:https://stackoverflow.com/questions/64944978/is-there-a-function-in-haskell-that-would-work-like-uniqueby