python3 排序 sort sorted

排序穩定性和排序複雜度

排序保證是 穩定 的。 這意味着當多個記錄具有相同的鍵值時,將保留其原始順序。

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> sorted(data, key=itemgetter(0))
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]

注意 blue 的兩個記錄如何保留它們的原始順序,以便 ('blue', 1) 保證在 ('blue', 2) 之前。

這個美妙的屬性允許你在一系列排序步驟中構建複雜的排序。例如,要按 grade 降序然後 age 升序對學生數據進行排序,請先 age 排序,然後再使用 grade 排序:

>>> s = sorted(student_objects, key=attrgetter('age'))     # sort on secondary key
>>> sorted(s, key=attrgetter('grade'), reverse=True)       # now sort on primary key, descending
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

這可以被抽象爲一個包裝函數,該函數能接受一個列表以及字段和順序的元組,以對它們進行多重排序。

>>> def multisort(xs, specs):
...     for key, reverse in reversed(specs):
...         xs.sort(key=attrgetter(key), reverse=reverse)
...     return xs

>>> multisort(list(student_objects), (('grade', True), ('age', False)))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Python 中使用的 Timsort 算法可以有效地進行多種排序,因爲它可以利用數據集中已存在的任何排序。

使用 cmp 參數的舊方法

本 HOWTO 中給出的許多結構都假定爲 Python 2.4 或更高版本。在此之前,沒有內置 sorted()list.sort() 也沒有關鍵字參數。相反,所有 Py2.x 版本都支持 cmp 參數來處理用戶指定的比較函數。

在 Py3.0 中, cmp 參數被完全刪除(作爲簡化和統一語言努力的一部分,消除了豐富的比較與 __cmp__() 魔術方法之間的衝突)。

在 Py2.x 中, sort 允許一個可選函數,可以調用它來進行比較。該函數應該採用兩個參數進行比較,然後返回負值爲小於,如果它們相等則返回零,或者返回大於大於的正值。例如,我們可以這樣做:

>>> def numeric_compare(x, y):
...     return x - y
>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare) 
[1, 2, 3, 4, 5]

或者你可反轉比較的順序:

>>> def reverse_numeric(x, y):
...     return y - x
>>> sorted([5, 2, 4, 1, 3], cmp=reverse_numeric) 
[5, 4, 3, 2, 1]

將代碼從 Python 2.x 移植到 3.x 時,如果用戶提供比較功能並且需要將其轉換爲鍵函數,則會出現這種情況。 以下包裝器使這很容易:

def cmp_to_key(mycmp):
    'Convert a cmp= function into a key= function'
    class K:
        def __init__(self, obj, *args):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        def __ne__(self, other):
            return mycmp(self.obj, other.obj) != 0
    return K

要轉換爲鍵函數,只需包裝舊的比較函數:

>>> sorted([5, 2, 4, 1, 3], key=cmp_to_key(reverse_numeric))
[5, 4, 3, 2, 1]

在 Python 3.2 中, functools.cmp_to_key() 函數被添加到標準庫中的 functools 模塊中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章