我目前正在用 Elm 编写一个基于网络的词汇训练器。这需要通过自定义比较器对单词列表进行排序。
我要排序的类型是:
type alias Word =
{ id: Int
, sourceWord: String
, targetWord: String
, numTries: Int
, numCorrect: Int
, createdAt: Maybe Date -- might be empty, therefore wrapped in Maybe
, lastAskedAt: Maybe Date -- might be empty, therefore wrapped in Maybe
}
类型别名 WordList = List (Word)
我的比较规则是(按重要性降序排列):
我能想到的最好方法是:
compareWords: Word -> Word -> Basics.Order
compareWords w1 w2 =
let
dateToComparable d = Date.Format.format "%Y-%m-%d" d
orderNumCorrect = compare w1.numCorrect w2.numCorrect
orderNumTries = compare w2.numTries w1.numTries -- switch ordering to sort descending
orderLastAskedAt = case (w1.lastAskedAt, w2.lastAskedAt) of
(Just a1, Just a2) -> compare (dateToComparable a1) (dateToComparable a2)
(Nothing, Just _) -> Basics.LT
(Just _, Nothing) -> Basics.GT
(Nothing, Nothing) -> Basics.EQ
orderCreatedAt = case (w2.createdAt, w1.createdAt) of -- switch ordering to sort descending
(Just a1, Just a2) -> compare (dateToComparable a1) (dateToComparable a2)
(Nothing, Just _) -> Basics.LT
(Just _, Nothing) -> Basics.GT
(Nothing, Nothing) -> Basics.EQ
in
case orderNumCorrect of
Basics.EQ -> case orderNumTries of
Basics.EQ -> case orderLastAskedAt of
Basics.EQ -> orderCreatedAt
_ -> orderLastAskedAt
_ -> orderNumTries
_ -> orderNumCorrect
我不喜欢的原因有很多:
Date.Format.format
(来自 mgold/elm-date-format)比较日期值(因为 Date 显然不是 comparable
)有没有更优雅/Elm-ish 的方式来实现我想要的?
更新+解决方案
正如@“Zimm i48”在他们最出色的答案中所建议的那样,这是一个使用 elm-ordering package 的更短的版本:
dateToComparable : Maybe Date -> Time
dateToComparable =
Maybe.map Date.toTime >> Maybe.withDefault 0
compareWords : Ordering Word
compareWords =
Ordering.byField .numCorrect
|> Ordering.breakTiesWith (Ordering.byField (.numTries >> negate))
|> Ordering.breakTiesWith (Ordering.byField (.lastAskedAt >> dateToComparable))
|> Ordering.breakTiesWith
(Ordering.byField (.createdAt >> dateToComparable >> negate))
最佳答案
多亏了 |>
,一种更像 Elm 风格的方法是组合式的。运算符(operator)。
elm-ordering库提供了执行此类操作所需的原语,尤其是 Ordering.byField
和 Ordering.breakTiesWith
职能。
至于日期,我的建议是使用 Date.toTime
(结果值具有可比性)。
奖励:您的订购功能的完整实现可在此处进行测试:https://runelm.io/c/xoz .你可以看到它比你的更简单,更易读......
关于comparison - 如何比较 Elm 中的多个字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41535288/