【问题标题】:How can I compare elements of two lists according to one predicate and select according to another?如何根据一个谓词比较两个列表的元素并根据另一个进行选择?
【发布时间】:2016-10-30 14:59:33
【问题描述】:

我想要实现的是将两个元组列表与((==) `on` fst) 进行比较,并从满足此谓词的对中选择满足(min `on` snd) 的对

【问题讨论】:

  • 查看Data.List。您正在寻找groupByminimumBy

标签: list haskell tuples


【解决方案1】:

我会假设...

我想要实现的是将两个元组列表与((==) `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.

【讨论】:

    【解决方案2】:

    要解决一般情况,您可以定义过滤器的修改版本,该版本与包含两个谓词的元组进行模式匹配,并检查两者是否都满足。

    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 的每个案例。
    猜你喜欢
    • 2021-04-07
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多