假设我有一个类似于以下示例的元组列表:
[(5, "a"), (1, "c"), (7, "d")]
在Elm中,我如何通过第一个元素按升序对列表进行排序,以便得到以下结果?
[(1, "c"), (5, "a"), (7, "d")]
使用Elm List documentation,sortBy
和sortWith
函数似乎对此案例有用。我对实施的尝试如下:
maxTuples : Tuple(a, b) -> Tuple(a, b) -> Tuple(a, b)
maxTuples t1 t2 =
case compare t1 t2 of
((Tuple.first t1) >= (Tuple.first t2)) -> GT
_ -> LT
sortByFirst : List (Tuple (a, b)) -> List (Tuple (a, b))
sortByFirst lst =
List.sortWith maxTuples lst
但是,我遇到了以下性质的编译器错误:
I ran into something unexpected when parsing your code!
99| ((Tuple.first t1) >= (Tuple.first t2)) -> GT
^
I am looking for one of the following things:
an upper case name
我的预感是,编译器正在根据GT
库的API查找LT
/ EQ
/ List
,但如果是这样,我不是确定我们如何能够使用sortBy
或sortWith
按照每个元素的第一个索引对Elm中的元组列表进行排序。
答案 0 :(得分:5)
您找到了正确的功能。在您的代码中,实际上存在多个问题:
(a, b)
,而不是Tuple(a, b)
。t1
与t2
进行比较,后者会按字典顺序比较元组。你真的想要compare (Tuple.first t1) (Tuple.first t2)
case
分支需要->
之前的模式。在这种情况下,类似EQ
,因为您匹配compare
的结果,返回Order
类型。你可以修改这样的代码:
maxTuples : (comparable, b) -> (comparable, b) -> (comparable, b)
maxTuples t1 t2 =
case compare (Tuple.first t1) (Tuple.first t2) of
GT -> GT
EQ -> EQ
_ -> LT
但是现在有一个不必要的重复,你只是返回compare
函数的结果。
maxTuples t1 t2 =
compare (Tuple.first t1) (Tuple.first t2)
与sort函数一起,它看起来像这样:
sortByFirst lst =
List.sortWith (\t1 t2 -> compare (Tuple.first t1) (Tuple.first t2)) lst
事实证明,这种操作很常见,特别是对于记录列表。出于这个原因,Elm提供了另一个功能 - sortBy
。它需要一个函数并在应用函数后比较元素:
sortBy f lst =
List.sortWith (\a b -> compare (f a) (f b)) lst
因此,您可以使用sortBy
函数来大大简化代码:
sortByFirst : List (comparable, b) -> List (comparable, b)
sortByFirst =
sortBy Tuple.first
答案 1 :(得分:4)
值得注意的是,你想要的是List.sort
的默认行为(sort将使用元组的第一个元素来排序列表,如果两个元素具有相同的第一个元素将移动以比较第二个元素等等)
List.sort [(5, "a"), (1, "c"), (1, "a"), (7, "d")] == [(1,"a"),(1,"c"),(5,"a"),(7,"d")]
在这种情况下使用sortBy是多余的。
答案 2 :(得分:0)
我不确定compare
中的case compare t1 t2 of
是什么,但您可以使用直线if
代替case
(并且还可以使用解构来代替如果您愿意,可以Tuple.first
:
maxTuples ( val1, _ ) ( val2, _ ) =
if val1 >= val2 then
GT
else
LT
我在https://ellie-app.com/ZZ9Hzhg7yva1/2有一个完整的工作示例(还需要进行一些类型注释更改才能进行编译)
但是,sortBy
是更简单的选项,因为它可以只需Tuple.first
对其中的任何内容进行排序:
sortByFirst lst =
List.sortBy Tuple.first lst