【发布时间】:2016-10-30 14:59:33
【问题描述】:
我想要实现的是将两个元组列表与((==) `on` fst) 进行比较,并从满足此谓词的对中选择满足(min `on` snd) 的对
【问题讨论】:
-
查看
Data.List。您正在寻找groupBy和minimumBy。
我想要实现的是将两个元组列表与((==) `on` fst) 进行比较,并从满足此谓词的对中选择满足(min `on` snd) 的对
【问题讨论】:
Data.List。您正在寻找groupBy 和minimumBy。
我会假设...
我想要实现的是将两个元组列表与
((==) `on` fst)进行比较
... 表示将一个列表中的每一对与另一个列表中的对应对进行比较,就像通常的 (==) 列表一样。
这是一个与您最初的建议保持接近的主要无点(也许有点古怪)的解决方案:
-- 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)]
关于写作minBy'的替代方式,请参阅。 Maximizing according to a function.
【讨论】:
要解决一般情况,您可以定义过滤器的修改版本,该版本与包含两个谓词的元组进行模式匹配,并检查两者是否都满足。
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
)
这将使用第一个谓词 odd 和第二个谓词 even 评估列表 [(1,2),(2,2),(3,3),(3,4)]:
>> filter' (odd,even) [(1,2),(2,2),(3,3),(3,4)]
[(1,2),(3,4)]
【讨论】:
(++) 中附加单个元素来重建带有foldl 的列表并不是一个好主意——请改用foldr 和(:)。此外,没有必要重新实现整个事情。你可以重复使用filter 就好了,比如filter' p q = filter (uncurry (&&) . bimap p q)。
foldr,尽管您包含的内容更好/更简洁。
bimap函数是什么?
Data.Bifunctor,可用于将两个不同的函数映射到例如(a, b) 对的每个组件或Either a b 的每个案例。