记录列表中的最大值
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
假设我在 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