【C#】配列やListをソートする方法

システム開発

C#で複雑なデータ構造を扱う際、クラス内にリスト(List<T>)や配列(T[])を持つオブジェクトの並び替えが必要になることがあります。

例えば、「List<AAA>の各要素がList<BBB>を持っている」ような場合、親オブジェクト(AAA)で並び替えるのか、子オブジェクト(BBB)をソートするのかで実装方法が異なります。

この記事では、「クラス内のリスト(または配列)を持つオブジェクトの並び替え」について、実際のコードとともに解説します!


クラスの定義と基本データ

この記事で扱う並び替えの前提となるクラス構造を定義しておきます。ソート対象が単なる数値や文字列ではなく、クラス内に他のコレクション(Listや配列)を含む複雑な構造の場合、適切な設計と処理が重要になります。

クラス構造の定義

以下のように、親クラス AAAList<BBB> を保持する構造を例にとります。

C#でのクラス定義

csharp
コピーする編集する
class AAA
{
    public string A { get; set; }
    public int B { get; set; }
    public List<BBB> BBBList { get; set; } // 子要素をリストで保持
}

class BBB
{
    public string AAA { get; set; }
    public int BBB { get; set; }
}

ポイント

  • AAA クラスは、名前(A)とソート対象となる数値(B)、さらに List<BBB> を保持しています。
  • BBB クラスは、親クラスとの関連を持つ AAA(名前)と、並び替え対象となる BBB(数値)を持ちます。

このような構造により、親(AAA)の並び替え子(BBBList)の並び替え、またはその両方を実現できます。以降ではこの構造をもとに、実際の並び替え実装を見ていきましょう。


親オブジェクト(AAA)を並び替える

まずは、親クラスである AAA オブジェクトの並び替え方法を見ていきましょう。特に「B の値を基準に昇順または降順に並び替えたい」といったケースはよくあります。

親のプロパティ(B)を基準にソート

C#でのソート例(昇順)

List<AAA> test = new List<AAA>
{
    new AAA { A = "X", B = 3, BBBList = new List<BBB> { new BBB { AAA = "X1", BBB = 30 } } },
    new AAA { A = "Y", B = 1, BBBList = new List<BBB> { new BBB { AAA = "Y1", BBB = 10 } } },
    new AAA { A = "Z", B = 2, BBBList = new List<BBB> { new BBB { AAA = "Z1", BBB = 20 } } }
};

// B の値で昇順ソート
test.Sort((a, b) => a.B.CompareTo(b.B));

foreach (var item in test)
{
    Console.WriteLine($"{item.A}, {item.B}");
}

✅ 出力結果

Y, 1
Z, 2
X, 3

ポイント

  • List<T>.Sort を使い、ラムダ式 (a, b) => a.B.CompareTo(b.B) でソート。
  • CompareTo を使うことで、自然な数値の昇順が実現できます。
  • 降順にしたい場合は、比較の順序を逆にして b.B.CompareTo(a.B) にすればOKです。

このように、親オブジェクトの並び替えは非常にシンプルですが、業務ロジックにおいてはデータの正しい順序が重要となるため、確実に理解しておきましょう。


子オブジェクト(BBB)を並び替える

次に、親クラス AAA の並び順はそのままに、各 AAA が持つ BBBList(子リスト)の内容を並び替える方法を解説します。親と子のどちらの順序を重視するかによって処理内容が変わるため、この違いを理解しておくことは重要です。

子リスト(BBBList)をソート

C#でのソート例(昇順)

foreach (var item in test)
{
    item.BBBList.Sort((b1, b2) => b1.BBB.CompareTo(b2.BBB));
}

foreach (var item in test)
{
    Console.WriteLine($"{item.A}, {item.B}");
    foreach (var bbb in item.BBBList)
    {
        Console.WriteLine($"  {bbb.AAA}, {bbb.BBB}");
    }
}

ポイント

  • AAA オブジェクトに対してループし、その中の BBBListSort で並び替えます。
  • 並び替え対象は BBB.BBB という整数プロパティです。
  • List<T>.Sort はインスタンスメソッドであり、リスト自体の順序を直接変更します。

このように、子要素だけをソートすることで、親の並びは維持したまま、内部のデータを整理できます。UIで詳細表示する際や、レポート生成などでよく使われるパターンです。


親オブジェクトと子オブジェクトを両方並び替える

実務では「親も子も並び替えたい」というケースがよくあります。例えば、親(顧客)を名前順に並べつつ、その顧客が持つ注文情報(子)を日付順に並べるといった場面です。このような場合、親→子の順に並び替え処理を行うのが基本です。

親も子も昇順でソートする方法

C#でのソート例

// 親オブジェクト(AAA)の並び替え
test.Sort((a, b) => a.B.CompareTo(b.B));

// 各親オブジェクトの子リスト(BBBList)の並び替え
foreach (var item in test)
{
    item.BBBList.Sort((b1, b2) => b1.BBB.CompareTo(b2.BBB));
}

foreach (var item in test)
{
    Console.WriteLine($"{item.A}, {item.B}");
    foreach (var bbb in item.BBBList)
    {
        Console.WriteLine($"  {bbb.AAA}, {bbb.BBB}");
    }
}

ポイント

  • まず List<T>.Sort で親オブジェクト(AAA)の B を昇順に並び替えます。
  • 次に、各 AAA が保持する BBBList をループで処理し、BBB.BBB を基準にソート。
  • それぞれの Sort元データに対して破壊的(in-place)に変更するので、効率的です。

このように処理を分けることで、親と子のソート基準を個別に制御でき、柔軟なデータ表示や処理が可能になります。特にツリー構造の表示や集計結果の整列などで役立つテクニックです。


配列(BBB[])を持つ場合の並び替え

前節までは子要素を List<BBB> として保持するケースを扱いましたが、場合によっては 配列(BBB[]) を使っているプロジェクトもあります。配列を使う場合、並び替えには Array.Sort を利用します。

子要素が配列の場合のソート方法

まず、BBBListBBB[] に変更したクラス定義の例です。

C#での配列を持つクラス定義

class AAA
{
    public string A { get; set; }
    public int B { get; set; }
    public BBB[] BBBArray { get; set; } // List ではなく配列で保持
}

このような配列を並び替えるには、Array.Sort を使います。

C#でのソート例(昇順)

foreach (var item in test)
{
    Array.Sort(item.BBBArray, (b1, b2) => b1.BBB.CompareTo(b2.BBB));
}

ポイント

  • Array.Sort(配列, 比較関数) という形で使用します。
  • 並び替えは破壊的で、元の配列の順序が変更されます(新しい配列は返されません)
  • List<T> に慣れていると、戻り値がないことに注意が必要です。

このように、List と配列ではソート方法に若干の違いがあるため、データ構造に合わせた適切な手法を選択することが大切です。配列を使う場面ではメモリやパフォーマンスを意識した設計になっているケースも多いため、特に慎重に扱いましょう。


まとめ

この記事では、C#で「クラス内にリストや配列を持つオブジェクトの並び替え」について解説しました。複雑なデータ構造でも、適切なソート処理を行うことで、目的に応じたデータの整理や表示が可能になります。

✅ ポイントの振り返り

  • 親オブジェクトを並び替える場合List<T>.Sort を使い、親のプロパティ(例:B)を基準に並び替え。
  • 子オブジェクトを並び替える場合:各親オブジェクトの List<BBB>BBB[] に対して Sort または Array.Sort を適用。
  • 親と子の両方を並び替える場合:まず親を並び替え、その後に各子リストや配列を個別に並び替えることで柔軟に対応可能。
  • Listと配列の違いList<T>Sort メソッドを直接持ち、ArrayArray.Sort を使用する点に注意。

データの並び順はユーザー体験や集計処理に大きく影響を与える重要な要素です。今回の内容を活用し、状況に応じたソート処理を実装してみてください。

コメント

タイトルとURLをコピーしました