记录列表中的最大值

Maximum in List of Records

假设我在 elm 中有一个记录列表:

[ { id = 1, magnitude = 100 }
, { id = 3, magnitude = 300 }
, { id = 2, magnitude = 200 } ]

并且我想要获得具有最大幅度值 (300) 的记录。这样做的好方法是什么?

docs 给出了一个使用 "maximum" 方法的例子,但它使用了一个简单的整数列表。它是如何处理记录的?

更新 根据@robertjlooby

的推荐

有一个名为 maximumBy 的函数在 elm-community/list-extra 中就是这样做的。示例:

List.Extra.maximumBy .magnitude list

原答案

有几种方法可以实现这一点。

第一种方式更简洁,但它涉及对整个列表进行排序,反转它,然后取头部。

maxOfField : (a -> comparable) -> List a -> Maybe a
maxOfField field =
  List.head << List.reverse << List.sortBy field

如果您想要更高效且只遍历列表一次的东西,这里有一个更高效的版本:

maxOfField : (a -> comparable) -> List a -> Maybe a
maxOfField field =
  let f x acc =
    case acc of
      Nothing -> Just x
      Just y -> if field x > field y then Just x else Just y 
  in List.foldr f Nothing

使用示例:

list =
  [ { id = 1, magnitude = 100 }
  , { id = 3, magnitude = 300 }
  , { id = 2, magnitude = 200 } ]

main =
  text <| toString <| maxOfField .magnitude list

这里是使用 foldl 和默认记录的版本:

bigger =
    let
        choose x y =
            if x.magnitude > y.magnitude then
                x
            else
                y
    in
        List.foldl choose {id = 0, magnitude = 0} items

Sebastian 的回答添加了一个任意的起始值,如果您的所有量级都是负数,这可能会导致问题。我会调整到

bigger items =
    case items of 
        [] -> []
        (h :: []) -> h
        (h :: tail) ->
            let
                choose x y =
                    if x.magnitude > y.magnitude then
                        x
                    else
                        y
            in
                List.foldl choose h tail