C#のList<T>で要素を入れ替える

コンピュータ

C#でコレクションを扱っていると、

  • 並び順を変更したい

  • ドラッグ&ドロップで要素を入れ替えたい

  • 特定の2要素だけを交換したい

といった場面があります。

この記事では、List<T> の要素を入れ替える方法を紹介します。

インデックス指定で入れ替える

List<T> はインデックスアクセスが可能なので、
一時変数を使えば最も素直に要素を入れ替えられます。

var list = new List<int> { 1, 2, 3, 4 };

int temp = list[1];
list[1] = list[3];
list[3] = temp;

Console.Write($"結果: ");
foreach(int x in list)
{
    Console.Write($" {x}");
}
Console.WriteLine("");
// 結果:  1 4 3 2

一時変数を使うオーソドックスな方法になりました。

 

ジェネリックメソッドとして切り出す

同じ処理を何度も書きたくない場合は、
ヘルパーメソッドにしておくと便利です。

static void Swap<T>(List<T> list, int indexA, int indexB)
{
    T temp = list[indexA];
    list[indexA] = list[indexB];
    list[indexB] = temp;
}

// 以下Swap<T>を呼び出すコード

var list = new List<int> { 1, 2, 3, 4 };

Swap<int>(list, 1, 3);

Console.Write($"結果: ");
foreach(int x in list)
{
    Console.Write($" {x}");
}
Console.WriteLine("");
// 結果:  1 4 3 2

範囲チェックを入れて安全版にする

indexがlistの範囲内かのチェックは定番で、概ね同じコードになりますので、メソッド内に埋め込むことが出来そうです。

static bool TrySwap<T>(List<T> list, int indexA, int indexB)
{
    if (list == null) return false;
    if (indexA < 0 || indexA >= list.Count) return false;
    if (indexB < 0 || indexB >= list.Count) return false;
    if (indexA == indexB) return true;
    
    T temp = list[indexA];
    list[indexA] = list[indexB];
    list[indexB] = temp;

    return true;
}

// 以下Swap<T>を呼び出すコード

var list = new List<int> { 1, 2, 3, 4 };
bool result = TrySwap<int>(list, 0, 5);
Console.WriteLine($"{result}");
// False

 

LINQ のソート系やSpan<T>は「仮想の並べ替え・参照」

C# には LINQ の OrderBy / ThenBySpan<T> など、
一見すると要素を並べ替えているように見える仕組みがあります。

しかし、これらの多くは 「実体の並び替え」ではなく「仮想の並べ替え」 です。


LINQ のソートは「新しい列を作る」

var sorted = list.OrderBy(x => x);

このコードは、

  • list 自体を書き換えている
    → ❌ 書き換えていない

  • 並び替え結果を「別の列」として返している
    → ⭕ 正しい

LINQ のソート系は 元の List<T> の要素順を変更しません

あくまで

「並び替えた結果を、そう見える形で列挙する」

という ビュー(View)を作っているだけ です。


Span<T> は「要素の参照」

Span<T> は高速で低レベルな印象がありますが、

Span<int> span = list.AsSpan();

これは

  • 新しい配列を作る

  • 要素の順番を変える

といった処理ではありません。

Span<T>同じメモリを別の視点で参照しているだけ

こちらもビュー(View)を作っているだけといえます。


「並び替えたい」のか「表示を変えたい」のか

やりたいこと 適した手段
データそのものの順序を変えたい List<T> の Swap / Sort
表示順だけ変えたい LINQ (OrderBy)
高速に部分データを扱いたい Span<T>

特に GUI アプリでは、

  • 内部データはそのまま

  • 表示だけ並び替える

という設計もよくあります。

最後に

要素の入れ替えは昔からある定番コードフローで、LINQが出てきてお役御免となったかと思もいましたが、そうでも無くいまだ現役なかんじです。

コメント