List 如何根据一个谓词比较两个列表的元素,并根据另一个谓词进行选择?
我试图实现的是比较两个元组列表与List 如何根据一个谓词比较两个列表的元素,并根据另一个谓词进行选择?,list,haskell,tuples,List,Haskell,Tuples,我试图实现的是比较两个元组列表与(==)on`fst,并从满足此谓词的元组对中,选择满足(min`on`snd)的元组来解决一般情况,您可以定义过滤器的修改版本,该模式匹配包含两个谓词的元组,并检查两者是否都满足 filter' :: ((a->Bool),(a->Bool)) -> [(a,a)] -> [(a,a)] filter' (pred1,pred2) = foldr f [] where f = (\x acc -> if pred1 $ fst x
(==)on`fst
,并从满足此谓词的元组对中,选择满足(min`on`snd)
的元组来解决一般情况,您可以定义过滤器的修改版本,该模式匹配包含两个谓词的元组,并检查两者是否都满足
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
)
这将使用第一个谓词奇数和第二个谓词偶数对列表[(1,2)、(2,2)、(3,3)、(3,4)]
进行评估,如下所示:
>> filter' (odd,even) [(1,2),(2,2),(3,3),(3,4)]
[(1,2),(3,4)]
为了解决一般情况,您可以定义过滤器的修改版本,该模式匹配包含两个谓词的元组,并检查两者是否都满足
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
)
这将使用第一个谓词奇数和第二个谓词偶数对列表[(1,2)、(2,2)、(3,3)、(3,4)]
进行评估,如下所示:
>> filter' (odd,even) [(1,2),(2,2),(3,3),(3,4)]
[(1,2),(3,4)]
我假设
我试图实现的是将两个元组列表与`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
对于编写minBy'
,cf..的替代方法,我假设
我试图实现的是将两个元组列表与`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
有关编写minBy'
的其他方法,请参见。您正在寻找groupBy
和minimumBy
。请查看。您正在寻找groupBy
和minimumBy
。使用foldl
重建列表,方法是在(++)
中添加单个元素,而不是使用foldr
和(:)
。此外,没有必要重新实施整个计划。您可以使用类似于filter'pq=filter(uncurry(&&&).bimap pq)之类的工具重新使用filter
,这很好。将我的实现更改为使用foldr
,但您所包含的内容更简洁/更好。您正在使用的bimap
函数是什么?它位于数据中。Bifunctor
,可用于将两个不同的函数映射到的每个组件(a,b)
成对或每种情况下的或a b
。使用foldl
重新生成一个列表,方法是在(++)
中添加单个元素,而不是使用foldr
和(:)
。此外,没有必要重新实施整个计划。您可以使用类似于filter'pq=filter(uncurry(&&&).bimap pq)之类的工具重新使用filter
,这很好。将我的实现更改为使用foldr
,但您所包含的内容更为简洁。您使用的bimap
函数是什么?它位于数据中。Bifunctor
,可用于将两个不同的函数映射到(a,b)
对的每个组件或或的每个案例。