Reputation: 483
What I am trying to achieve is to compare two lists of tuples with ((==) `on` fst)
and out of the pairs that satisfy this predicate, select the ones that satisfy (min `on` snd)
Upvotes: 0
Views: 484
Reputation: 34398
I will assume that...
What I am trying to achieve is to compare two lists of tuples with
((==) `on` fst)
... means comparing each pair in one list with the corresponding pair in the other list, as in the usual (==)
for lists.
Here is a mostly pointfree (and perhaps slightly cranky) solution that stays close to your original suggestions:
-- Suggestions of sensible names for this are welcome.
yourSelector :: (Eq a, Ord b) => [(a, b)] -> [(a, b)] -> [(a, b)]
yourSelector ps = fmap (minBy' snd)
. filter (uncurry ((==) `on` fst)) . zip ps
where
minBy' f (x, y) = case (compare `on` f) x y of
LT -> x
_ -> y
GHCi> yourSelector [(1,2),(3,5),(4,7)] [(1,3),(2,2),(4,9)]
[(1,2),(4,7)]
For alternative ways of writing minBy'
, cf. Maximizing according to a function.
Upvotes: 2
Reputation: 2625
To solve a general case, you can define modified version of filter that pattern-matches a tuple containing two predicates and checks if both are satisfied.
filter' :: ((a->Bool),(a->Bool)) -> [(a,a)] -> [(a,a)]
filter' (pred1,pred2) = foldr f []
where f = (\x acc -> if pred1 $ fst x then
if pred2 $ snd x then x : acc
else acc
else acc
)
Which would evaluate a list [(1,2),(2,2),(3,3),(3,4)]
with the first predicate odd
and the second predicate even
as:
>> filter' (odd,even) [(1,2),(2,2),(3,3),(3,4)]
[(1,2),(3,4)]
Upvotes: 1