【问题标题】:Max in a list and its index in Haskell -- in the case of a tie, I need the element closest to the head列表中的最大值及其在 Haskell 中的索引——在平局的情况下,我需要最靠近头部的元素
【发布时间】:2025-12-12 20:40:02
【问题描述】:

我的代码如下 (value, index) = maximumBy (comparing fst) (zip list [0..]) 在大多数情况下工作正常,但是,在平局的情况下,它返回最接近尾部的索引,这与我想要的相反。 也就是说,如果列表是xs = [2,7,3,7],我希望它返回(7,1) 而不是(7,3)。有没有简单的方法,或者我需要完全重写它?

【问题讨论】:

  • 您当前的测试只是comparing fst,因此它完全忽略了索引(snd)。您可能希望使用更复杂的测试,也就是适当考虑索引的测试。
  • minimumBy (comparing (first Down)) $ zip [1,7,2,7] [0..]。或maximumBy (comparing (second Down)) $ ...。虽然这取决于Ord 中的索引。
  • @jpmarinier 到 your comment 在现已删除的 Q 上,指向指南的是 amalloy,而不是我。根据他们的解释,我发表上述评论也犯下了不可饶恕的罪行。
  • @WillNess - 是的,很抱歉造成混乱。当问题在我脚下被删除时,我刚刚发现了我的错误。所以我没有时间将我的评论重定向到 amalloy。所以是这样的丛林:-) 无论如何感谢你找到一种方法回到我身边。

标签: list haskell indexing


【解决方案1】:
有没有一种简单的方法可以做到这一点,还是我需要完全重写它?

如果您坚持重用库 maximumBy 函数,您可以这样做:将 fst 参数替换为更合适的 comparing

例如,对索引取反以使比较结果相反。

 λ> 
 λ> xs = [2,7,3,7]
 λ> 
 λ> maximumBy  (comparing (\(v,x) -> (v,-x)))  (zip xs [0..])
 (7,1)
 λ> 

如果您熟悉 Haskell Arrow 工具,可以用更简洁的方式表达相同的想法:

 λ> 
 λ> import Control.Arrow
 λ> 
 λ> maximumBy  (comparing (second id))  (zip xs [0..])
 (7,3)
 λ> 
 λ> maximumBy  (comparing (second negate))  (zip xs [0..])
 (7,1)
 λ> 
 λ> maximumBy  (comparing (id *** negate))  (zip xs [0..])
 (7,1)
 λ> 

【讨论】:

    【解决方案2】:

    这是maximumBy的源代码

    maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a
    maximumBy cmp = foldl1 max'
      where max' x y = case cmp x y of
                            GT -> x
                            _  -> y
    

    所以根据定义它返回最右边的最大元素。 我想,获得最左边的最大元素的最直接方法是定义自己的 maximumBy' 像这样

    maximumBy' cmp = fold1 max'
      where max' x y = case cmp x y of
                            LT -> y
                            _  -> x
    

    所有其他方式以某种方式重新定义max,就像我们在这里所做的那样。

    这会给你:

    > maximumBy' (comparing fst) (zip xs [0..])
    > (7,1)
    

    【讨论】: