15
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Python] pathlib.Pathのリストを自然順ソートする

Last updated at Posted at 2019-12-09

概要

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()を使えばよいかと思います(モジュールは必要だけど).
ディレクトリじゃなくてファイルでも同様の方法が適用できるはずです.

15
13
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?