2017-04-25 54 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是多餘的。