Pythonでの不満。Python2にあったsorted関数のcmpがなくなって、keyになった。
なぜ、cmpはなくなったのだろうか?考えてみた。 まず、sortedへの不満として、複数キーの昇順・降順ができなくなった。というものがあった。 誤りである。 どうやらkeyにタプルを返すと勝手に複数キーの昇順としてソートしてくれるようだ。 つまり、文字は反転。数字はマイナスにすることで、それらしきものができる。 c=[('a', 1), ('a', 2), ('b', 2), ('b', 1)] sorted(c, key=lambda x: (tuple(map(lambda z:(0xff-z), x[0].encode("cp932"))), -x[1])) [('b', 2), ('b', 1), ('a', 2), ('a', 1)]ここで気づいた。この比較用キーの作成はcmpの場合、ソート方法に依存してしまう。O(2*NlogN)の頻度で比較用キーが作成されてしまうのだ。 この点、key指定だと比較用キーはO(N)のみの作成となる。 すばらしい ただし、文字列の降順としては可変長の場合、前述の方法は使えない。なので、classを作ってみた。 class Keys: def __init__(self, v, isAscs): self.v = v self.isAscs = tuple(isAscs) def __lt__(self, other): for i, s, isAsc, o in zip(range(len(self.isAscs)-1, -1, -1), self.v, self.isAscs, other.v): lt = [lambda p1, p2: p1 > p2, lambda p1, p2: p1 < p2][isAsc] ret = lt(s, o) if ret or i and lt(o, s): break return ret @staticmethod def of(isAscs, keymap=lambda x:x): return lambda item: Keys(keymap(item), isAscs) if __name__ == "__main__": arr = [("a", 2), ("b", 1), ("a", 1), ("b", 2)] print(arr) #1項目め降順、2項目め昇順 print(sorted(arr, key=Keys.of((False, True)))) #1項目め2文字目昇順、1項目め1文字目昇順 print(sorted(arr, key=Keys.of((True, False), keymap=lambda x:(x[0][1], x[0][0]))))うん、素晴らしい。 PR |
|
忍者ブログ [PR] |