概要
pathlib.Path形式の要素を持つリストには,natsorted()関数が適用できません.
そこで,自然順ソートするための関数を自作しました.
sorted()関数とnatsorted()関数
sorted()関数は,リストの要素を辞書順ソートする関数です.
例えばこのようなリストがあるとき,
strs = ["dir/10", "dir/1", "dir/3" , "dir/24"]
このように書けば,
for s in sorted(strs):
print(s)
こうなります.
dir/1
dir/10
dir/24
dir/3
辞書順なのでまあそうなるのが妥当なんですが,人間の感覚ではいささか気持ち悪いですね.
対してnatsorted()関数は,リストの要素を自然順ソートする関数(モジュールが必要)です.
同じリストに対して,このように書けば,
from natsort import natsorted
for s in natsorted(strs):
print(s)
こうなります.
dir/1
dir/3
dir/10
dir/24
やっぱり,こっちの方がしっくりきます.
natsorted()関数最高!
Pathが要素だとどうなるか
例えば下のようなディレクトリ構造のとき,
dir
├ 1
├ 3
├ 10
└ 24
このようにpathlib.Path形式のリストが作成できます.
pathlibモジュールに関しては調べれば解説がたくさん見つかるので割愛で.
import pathlib
paths = [p for p in pathlib.Path("./dir/").iterdir() if p.is_dir()]
じゃあこれを自然順ソートしてみると,
from natsort import natsorted
for p in natsorted(paths):
print(p)
こうなります.
dir\1
dir\10
dir\24
dir\3
辞書順じゃん!
まあきっとPath形式には対応していないんでしょうな.
だから辞書順で読み込んで,そのまんまになっていると.
要素はstrとかintじゃないといかんということですかね(記事投稿から数年たったが調べていない).
解決策
こんな関数を自作しました.
sorted()関数はkeyを引数に指定できることを利用しています.
#コメントでnatsorted()でも同じ書き方ができることを教えていただきました!
def paths_sorted(paths):
return sorted(paths, key = lambda x: int(x.name))
これをこうやって使えば,
for p in paths_sorted(paths):
print(p)
こうなります.
dir\1
dir\3
dir\10
dir\24
望み通りの結果が得られました!
その他
この場合はディレクトリ名が数値だったのでディレクトリ名をintに変換してkeyとしました.
no1, no2...みたいに文字列を含む場合はstrにしてnatsorted()を使えばよいかと思います(モジュールは必要だけど).
ディレクトリじゃなくてファイルでも同様の方法が適用できるはずです.