2017-04-25 51 views
4

元组的列表,假设我有一个类似于下面的示例元组的列表:排序他们的第一个指数榆树

[(5, "a"), (1, "c"), (7, "d")] 
在榆树

,我怎么去有关升序排序列表他们的第一个元素,以便我们得到以下结果?

[(1, "c"), (5, "a"), (7, "d")] 

使用Elm List documentation,看来该sortBysortWith功能将是这种情况下非常有用。我在执行尝试如下:

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/LT/EQList库的API,但如果这种情况下,我不知道我们将如何能够使用sortBysortWith排序在Elm的元组列表的每个元素的第一个索引。

回答

4

你找到了正确的功能。在您的代码中,实际上存在多个问题:

  1. 类型注释应该只是(a, b)而不是Tuple(a, b)
  2. 比较t1t2,它将按照字典顺序比较元组。你真的想要compare (Tuple.first t1) (Tuple.first t2)
  3. 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) 

,它应该是这样的:

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 
+0

编译器表明签名应该是 列表(可比,A2) - >列表(可比,A2) 但是这是个好主意。 –

+0

@AdamFreymiller是的,这是更精确。我将把它编辑成答案。 –

0

我不知道什么comparecase 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 

该版本是在https://ellie-app.com/ZZ9Hzhg7yva1/3

3

值得注意的是,你想要的是默认行为List.sort(排序将使用元组的第一个元素来排序列表,如果两个元素具有相同的第一个元素将移动以比较第二个元素等) List.sort [(5, "a"), (1, "c"), (1, "a"), (7, "d")] == [(1,"a"),(1,"c"),(5,"a"),(7,"d")]

在这种情况下使用sortBy是多余的。