📑

よくある自然順ソート (C#)

に公開

はじめに

書籍のタイトルのように連番付きの文字列をソートする際は、巻数の順に正しく並んで欲しいですよね。
よくある話で、実装例も数多あるようです。

前提

  • .NET 8

実装

https://github.com/tetr4lab/Tetr4labNugetPackages/blob/5dee11d532290f87afbe55525dbe1783fea82bbb/Tetr4lab/Scripts/NaturalSort.cs#L1-L43

decimalParseすることで、負数や桁区切りにも対応していますが、シンプルにintにする選択肢もあります。

OrdinalIgnoreCase(大小文字を区別しない)にしていますが、区別するように(Ordinal)するとか、区別しないにしてもCurrentCultureIgnoreCaseとか、いっそオプションにして都度指定できるようにするとか、いろいろ選択肢は考えられると思います。

使用例

string [] list = ["a10b", "a10bc", "a11", "a10aB", "a10aa", "a10ac", "a3", "a2a", "a1.5", "a-1a", "a9.5", "a-2", "A100"];
list.NaturalSort ();
Console.WriteLine (string.Join (", ", list));
結果(OrdinalIgnoreCase)
a-2, a-1a, a1.5, a2a, a3, a9.5, a10aa, a10aB, a10ac, a10b, a10bc, a11, A100

Ordinalだと、以下の結果になります。

結果(Ordinal)
A100, a-2, a-1a, a1.5, a2a, a3, a9.5, a10aB, a10aa, a10ac, a10b, a10bc, a11
蛇足

プロジェクト独自のクラスへの応用

using Cashbook.Data;
using Tetr4lab;

namespace Cashbook.Services;

/// <summary>自然順ソート</summary>
public static class NaturalSortHelper {
    /// <summary>自然順ソート用比較</summary>
    private static IComparer<string> _naturalSortComparer = new NaturalSortComparer ();
    /// <summary>自然順ソート</summary>
    public static void NaturalSort (this List<Transaction> list)
        => list.Sort ((x, y) => _naturalSortComparer.Compare (x.ItemDetail, y.ItemDetail));
}

おわりに

最後までお読みいただきありがとうございました。
何かお気づきの際は、是非コメントなどでご指摘ください。
あるいは、「それでも解らない」、「自分はこう捉えている」などといった、ご意見、ご感想も歓迎いたします。

Discussion