ファイルを名前順で並べたい
これは適当なフォルダをエクスプローラーで表示したもの。名前順で並んでいる。
このフォルダのファイルをSystem.IO.Directory.GetFiles(string path)で取得しファイル名を列挙すると、以下の様になる。
hoge1.wav
hoge15.wav
hoge2.wav
hoge4.wav
hoge3.wav
エクスプローラーの表示とは違う順番で並んでいる。
半角の数字から並べて、全角の数字は後で並べたというような順番だ。
普通にソートしてみる
じゃあ、並び替えをすればいいじゃないかとArray.Sortを実行してみると、これまた以下の様になる。
hoge1.wav
hoge15.wav
hoge2.wav
hoge3.wav
hoge4.wav
惜しい。惜しいけど違う。
恐らく全角数字と半角数字での比較もされるようになったのだろうが、二桁の数字をまとめて認識して、この中で15は最後だな、とするような気の利いたことはしてくれない。
同じ番目の文字同士でのみ比較している、所謂「辞書順」というやつだろうか。
自然順で並べる
「辞書式順序」をベースに、二桁以上の数字はまとめて認識して並び替えるようにしたものを
「自然順」と言うようだ。
この自然順の並び替えはWindowsのAPIに標準で存在し、以下の様にして簡単に比較クラス(IComparer<string>)を作成できる。
public class NaturalStringComparer : IComparer<string>
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(string psz1, string psz2);
public int Compare(string a, string b) => StrCmpLogicalW(a, b);
}
これをArray.SortやIEnumerable.OrderByなどに渡して使う。
Array.Sort(array, new NaturalStringComparer());
array = array.OrderBy(f => f, new NaturalStringComparer()).ToArray();
すると、このようにエクスプローラーと同じ並び順になる。めでたしめでたし。*1
hoge1.wav
hoge2.wav
hoge3.wav
hoge4.wav
hoge15.wav