Python 3 では sorted 関数に比較関数を渡すことが出来なくなったのだけど、Python 3.2 では functools.cmp_to_key を使えば、sorted 関数に比較関数を渡すのと同様のことが出来るようになった。いくつかサンプルを書いてみる。
はじめに、整数を文字列で比較してソートするサンプルを書いてみる。
from functools import cmp_to_key
def cmp(a, b):
if a == b: return 0
return -1 if a < b else 1
def cmpstr(a, b):
return cmp(str(a), str(b))
def main():
xs = [4, 90, -9, 12, 42]
print(sorted(xs, key=cmp_to_key(cmpstr)))
main()
実行結果です。
[-9, 12, 4, 42, 90]
大小の比較結果は -1, 0, 1 のいずれかを返す。小さければ -1 を返し、等しければ 0 を返し、大きければ 1 を返す。
ただ、この例に限っては、sorted(xs, key=str)
と書いても同じです。
functools.cmp_to_key
の使い方が分かったので、今度は本当にやりたかったソートをやってみる。2 つの要素を持つタプルのリストがあり、このリストをソートしたい。比較方法は、タプルの 2 番目の要素の小さい順、かつ、もし 2 番目の要素が等しいなら、1 番目の要素の大きい順にソートする。比較関数は以下のようになります。
from functools import cmp_to_key
def cmp(a, b):
if a == b: return 0
return -1 if a < b else 1
def cmptuple(a, b):
return cmp(a[1], b[1]) or cmp(b[0], a[0])
def main():
xs = [(4, 90), (-9, 12), (42, 12), (100, 12), (1, 1), (-123, 1)]
print(sorted(xs, key=cmp_to_key(cmptuple)))
main()
実行結果です。
[(1, 1), (-123, 1), (100, 12), (42, 12), (-9, 12), (4, 90)]