web-dev-qa-db-ja.com

カスタムPythonリストのソート

私は私の古いコードをリファクタリングしていて、これに出くわしました:

alist.sort(cmp_items)

def cmp_items(a, b):
    if a.foo > b.foo:
        return 1
    Elif a.foo == b.foo:
        return 0
    else:
        return -1

コードは機能します(3年ほど前に作成しました!)が、Pythonドキュメントのどこにも文書化されていないので、誰もがsorted()を使用してカスタムソートを実装しています。誰かがこれがなぜ機能するのか説明できますか?

72
Lorenzo

文書化されています ここ

Sort()メソッドは、比較を制御するためのオプションの引数を取ります。

cmpは、2つの引数(リスト項目)のカスタム比較関数を指定します。最初の引数が2番目の引数よりも小さい、等しい、または大きいと見なされるかどうかに応じて、負、ゼロ、または正の数を返します:cmp = lambda x、y :cmp(x.lower()、y.lower())。デフォルト値はなしです。

51
miles82

サイドノートとして、同じソートを実装するためのより良い代替手段があります:

alist.sort(key=lambda x: x.foo)

または、代わりに:

import operator
alist.sort(key=operator.attrgetter('foo'))

Sorting How To を確認してください。非常に便利です。

89
Andrew Clark

この例のように。このリストを並べ替えます。

[('c', 2), ('b', 2), ('a', 3)]

出力:

[('a', 3), ('b', 2), ('c', 2)]

タプルを2番目の項目、次に最初の項目でソートする必要があります。

def letter_cmp(a, b):
    if a[1] > b[1]:
        return -1
    Elif a[1] == b[1]:
        if a[0] > b[0]:
            return 1
        else:
            return -1
    else:
        return 1

最後に:

ただsort(letter_cmp)

10
RryLee

これはPython 3では機能しません。

Functools cmp_to_keyを使用して、古いスタイルの比較関数を機能させることもできます。

from functools import cmp_to_key

def cmp_items(a, b):
    if a.foo > b.foo:
        return 1
    Elif a.foo == b.foo:
        return 0
    else:
        return -1

cmp_items_py3 = cmp_to_key(cmp_items)

alist.sort(cmp_items_py3)
3
The Unfun Cat