簡體   English   中英

Python:如何在數字主排序中執行二次降序字母排序

[英]Python: How to perform a secondary descending alphabetic sort within a numeric primary sort

按兩個標准對 Python 列表進行排序中,福阿德給出了以下答案:

sorted(list, key=lambda x: (x[0], -x[1]))

我想主要在元組列表中對以下列表進行排序,主要在每個元素中的第二個項目上按升序排列,然后是第一個(字母)項目按降序排列:

[('Ayoz', 1, 18, 7), ('Aidan', 2, 4, 9), ('Alan', 2, 4, 9), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)] 

給出答案:

[('Ayoz', 1, 18, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9), ('Tariq', 5, 4, 2), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2)]

如果可能,使用上述方法。 我試過了

tlist = [('Ayoz', 1, 18, 7), ('Aidan', 2, 4, 9), ('Alan', 2, 4, 9), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)]
sorted(tlist, key=lambda elem: (elem[1], -elem[0]))

但這僅在 elem[0] 為數字時才有效(在這種情況下,它會給出 TypeError: bad operand type for unary -: 'str')

我將不勝感激任何幫助。 Python版本是3.4

Python 中內置的排序例程是穩定的。 也就是說,如果兩個項目具有相同的鍵值,那么它們將保持它們相對於彼此的順序(靠近列表前面的那個保持更靠近前面)。 因此,您可以使用多個排序通道對多個鍵進行排序。

from operator import itemgetter

tlist = [('Ayoz', 1, 18, 7), ('Aidan', 2, 4, 9), ('Alan', 2, 4, 9),
         ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)]

# sort by name in descending order
tlist.sort(key=itemgetter(0), reverse=True) 
print('pass 1:', tlist)

# sort by element 1 in ascending order.  If two items have the same value
# the names stay in the same order they had (descending order)
tlist.sort(key=itemgetter(1))
print(npass 2:', tlist)

印刷:

pass 1: [('Tariq', 5, 4, 2), ('Luke', 15, 16, 2), ('Ayoz', 1, 18, 7), ('Arlan', 5, 6, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9)]

pass 2: [('Ayoz', 1, 18, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9), ('Tariq', 5, 4, 2), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2)]
tlist = [('Ayoz', 1, 18, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)] 

sorted(tlist, key=lambda elem: (elem[1],sorted(elem[0],reverse=True)))

解決了,但我花了半個小時才打字,所以無論如何我都會發帖。 我仍然歡迎更好的方法。

您可以對原始答案進行修改以使其正常工作:

sorted(tlist, key=lambda elem: (-elem[1], elem[0]), reverse=True)

這是一個替代方案。 它的工作原理類似於使用 -number 來反轉排序順序的技巧,但適用於字母字符串。

下表將 'a' 映射到 'z','b' 映射到 'y' 等等。 t[0].translate(table)將 'Ayoz' 轉換為 'Zbla',因此 ('Ayoz', 1 , 18, 7) 是 (1, Zbla')

table = str.maketrans('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
                      'zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA')

tlist.sort(key=lambda t: (t[1], t[0].translate(table)))

我剛剛遇到這個問題,我驚訝地發現它是 Python 強大的排序中缺少的部分。 您可以反轉整體排序,但不能反轉子排序。 其他答案是可用的解決方法,但如果您有一個要使用不同子排序順序排序的字段列表,則它們不是通用解決方案,尤其是在不能選擇多遍排序的情況下。

這就是我最終的結果:

class inverse_str(str):
    """
    A string that sorts in inverse order.
    """
    def __lt__(self, rhs):
        return not super().__lt__(rhs)

data = [('Ayoz', 1, 18, 7), ('Aidan', 2, 4, 9), ('Alan', 2, 4, 9), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2), ('Tariq', 5, 4, 2)]
data.sort(key=lambda item: (item[1], inverse_str(item[0])))
print(data)

wanted = [('Ayoz', 1, 18, 7), ('Alan', 2, 4, 9), ('Aidan', 2, 4, 9), ('Tariq', 5, 4, 2), ('Arlan', 5, 6, 7), ('Luke', 15, 16, 2)]
print(data == wanted)

這與返回例如具有相同的效果。 浮點字段的鍵函數中的 1-item[1]。

RootTwo 的多級排序答案是有效的,但多步排序並不總是一種選擇。 我正在使用 heapq.merge 合並增量的先前排序的數據流,所以這不起作用。 在比較中執行此操作會在實際排序中執行此操作,因此您不需要多次傳遞,並且它適用於一般情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM