我目前正在用榆木写一个基于网络的词汇培训师。这需要通过自定义比较器对单词列表进行排序。
我要排序的类型是:
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
}
Run Code Online (Sandbox Code Playgroud)
类型别名WordList =列表(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
Run Code Online (Sandbox Code Playgroud)
我不喜欢的原因有很多:
Date.Format.format(从mgold / elm-date-format)比较Date值(因为Date显然不是comparable)有没有更优雅/榆木的方式来实现我想要的?
更新+解决方案
正如@“ Zimm i48”在其最出色的答案中所建议的,这是一个使用elm-ordering软件包的简短版本:
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))
Run Code Online (Sandbox Code Playgroud)
归功于|>操作员,一种更为Elm-ish的方式来完成这种事情是有条理的。在榆树排序库提供的原语,你需要做这样的事情,尤其是Ordering.byField和Ordering.breakTiesWith功能。
至于日期,我的建议是使用Date.toTime(结果值是可比较的)。
奖励:订购功能的完整实现可在此处进行测试:https : //runelm.io/c/xoz。您会发现它比您更简单,更易读...