2015-09-27 130 views
2

我前幾天纔開始學習Python,並且想實現我的小項目。我需要按數字值降序排列(string, integer)的列表,但按字母順序排列,如果數字對於多個元組是相同的。所以我有一個名單,說:元組列表的自定義排序

tuples = [('ggg', 5), ('aaa', 5), ('bbb', 6), ('zzz', 6)] 
tuples.sort(key=lambda score: score[1], reverse=True) 

這將返回:

[('bbb', 6), ('zzz', 6), ('ggg', 5), ('aaa', 5)] 

但我希望得到的是:

[('bbb', 6), ('zzz', 6), ('aaa', 5), ('ggg', 5)] 

在Java我只是實現了一個比較自定義元組:

class Pair { 
    public final String s; 
    public final Integer i; 

    public Pair(String s, Integer i) { 
     this.s = s; 
     this.i = i; 
    } 
} 

class PairComparator implements Comparator<Pair> { 

    @Override 
    public int compare(Pair p1, Pair p2) { 
     int c = p1.i.compareTo(p2.i); 
     return (c == 0) ? p1.s.compareTo(p2.s) : c * (-1); 
    } 
} 

但我的'我不知道如何在Python中使用lambda表達式。

+0

所以你想要降序的數字,然後升序的信件? –

+0

FWIW,Python 2爲'sort'(和'max'&'min')提供了一個自定義的比較函數參數,但是它已經在Python 3中逐漸淘汰了,因爲效率較低:只需要調用一次自定義的鍵函數對於每個鍵,但是在_every_比較時會調用一個自定義比較函數。 –

+0

它可以在Python 3中實現自定義比較:創建一個實現[豐富比較](https://docs.python.org/3/reference/datamodel.html#object.__lt__)方法的類。 OTOH,Python內置的'sort'(又名Timsort)是穩定的,所以用不同的密鑰對列表進行多次排序可能就足夠了,而不是在有複雜排序要求時使用自定義比較。 –

回答

2

也許最簡單的方法是將具有key返回一個元組,並乘以-1的成績。例如:

>>> tuples.sort(key=lambda x: (-x[1], x[0])) 
>>> tuples 
[('bbb', 6), ('zzz', 6), ('aaa', 5), ('ggg', 5)] 

這將按降序對整數進行排序,然後按升序對字符串進行排序。

+0

如果我發表評論,我應該知道我會忍者。 :) –

+1

它發生在我身上的次數超過了我的數量:-) –

1

你可以只排序,基於數的負形狀和不使用reverse=True

>>> >>> tuples.sort(key=lambda x:(-x[1],x[0])) 
>>> tuples 
[('bbb', 6), ('zzz', 6), ('aaa', 5), ('ggg', 5)] 
+1

如果你沒有在關鍵字中指定'x [0]',它將被忽略_並且由於Timsort是穩定的,所以基於'x [0]'的項目排序不會改變。在'[('bbb',6),('zzz',6),('aaa',5),('xxx',5),('ggg',5)]'上嘗試你的代碼。 –

+0

@ PM2Ring噢,我錯過了'lambda',感謝提醒。 – Kasramvd

0

另一種選擇是使用運算符模塊函數operator.itemgetter()對它們進行兩次排序。我們首先按升序對第一個元素進行排序,然後按降序對第二個元素進行排序(儘管效率較低)。

In [1]: from operator import itemgetter 

In [2]: tuples = [('ggg', 5), ('aaa', 5), ('bbb', 6), ('zzz', 6)] 

In [3]: tuples.sort(key=itemgetter(0)) # [('aaa', 5), ('bbb', 6), ('ggg', 5), ('zzz', 6)] 

In [4]: tuples.sort(key=itemgetter(1), reverse=True) # sort by 2nd element in descending order 

In [5]: tuples 
Out[5]: [('bbb', 6), ('zzz', 6), ('aaa', 5), ('ggg', 5)]