Posted at

[Python] iterableを複数条件でソート

More than 3 years have passed since last update.


組み込み関数:sorted


sorted(iterable[, key][, reverse])



  • 第一引数iterableの要素をソートしたリストを返り値として返す関数.

  • キーワード引数keyはiterableの要素がタプル等であれば
    key = lambda x: x[1]
    などで,何個目の要素を基準とするかを指定できる.(デフォルトはNoneでそのまま比較)

  • キーワード引数reverseにはbool値を与えます.Trueの場合は降順,Falseの場合は昇順(デフォルトはFalse[昇順])

参考サイト:2. 組み込み関数ーPython3.5.1 ドキュメント


複数条件のソート


なぜ複数条件のソートをしたかったか

glob等でファイル名リストを獲得してから,

ファイル名が(test_file_1.txt, test_file_2.txt, … test_file_19.txt, test_file_20.txt)のものを数字でソートしたい.

単純にソートしようとすると,


sort_test_1.py

>>> import random

>>> file_names = ["test_file_{}.txt".format(num) for num in range(1, 21)]
>>> random.shuffle(file_names)
>>> sorted(file_names)
['test_file_1.txt', 'test_file_10.txt', 'test_file_11.txt',
'test_file_12.txt', 'test_file_13.txt', 'test_file_14.txt',
'test_file_15.txt', 'test_file_16.txt', 'test_file_17.txt',
'test_file_18.txt', 'test_file_19.txt', 'test_file_2.txt',
'test_file_20.txt', 'test_file_3.txt', 'test_file_4.txt',
'test_file_5.txt', 'test_file_6.txt', 'test_file_7.txt',
'test_file_8.txt', 'test_file_9.txt']

先頭から見ていくので,1 の次が2になってほしいが,10になる.

(この場合はファイル名変えれば解決する問題だけど)

ここでは,タプルを使ってこの問題を解決する.


タプルの比較

Pythonでのタプルの比較は,最初の要素から順に見ていく.

e.g. (a, b, c) (d, e, f)の二つがあった場合, aとb,bとe,cとfの順に比較.

なので,keyを(x, y),xには数字が一桁だとわかるようなものを,yにはファイル名として設定するとうまくソートできる.

今回は,xにファイル名の長さを入れてソートする.


sort_test_2.py

>>> file_names = ["test_file_{}.txt".format(num) for num in range(1, 21)]

>>> random.shuffle(file_names)
>>> sorted(file_names, key=lambda x: (len(x), x))
['test_file_1.txt', 'test_file_2.txt', 'test_file_3.txt',
'test_file_4.txt', 'test_file_5.txt', 'test_file_6.txt',
'test_file_7.txt', 'test_file_8.txt', 'test_file_9.txt',
'test_file_10.txt', 'test_file_11.txt', 'test_file_12.txt',
'test_file_13.txt', 'test_file_14.txt', 'test_file_15.txt',
'test_file_16.txt', 'test_file_17.txt', 'test_file_18.txt',
'test_file_19.txt', 'test_file_20.txt']


まとめ


  • 組み込み関数にあるsortedの簡単な使い方

  • タプル使うと簡単に複数条件でソートができる