C#

【C#】 Listの要素を削除する方法

こんにちは、リバティエンジニア[?]のFUNAです。 現役エンジニアとしてアプリケーション開発やWeb制作、SEOやブログ運営をしています。

C#でよく利用するコレクションに"List"があります。
以前の記事で詳しく解説しているので、Listコレクションについて知りたい方はそちらを見てみてください。

http://itthestudy.com/c-list%E3%81%AB%E8%A6%81%E7%B4%A0%E3%82%92%E8%BF%BD%E5%8A%A0%EF%BC%8F%E6%8C%BF%E5%85%A5%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%EF%BC%9F/

今回はそんな"List"コレクションの要素を削除する方法をご紹介します。

C# Listコレクションの要素

まず"List"コレクションの要素について簡単に説明します。

Listに要素を追加する際にはコンストラクタでの初期化時、もしくはaddメソッドを使います。

List<int> integerList = new List<int>();
integerList.Add(2);
integerList.Add(3);
integerList.Add(4);

このように要素を追加することでこの"integerList"には、
0要素目に【2】
1要素目に【3】
2要素目に【4】
が入っている状態です。

皆さん御存知のとおり、要素は0(ゼロ)から始まるので注意してください。

C# Listコレクションの要素を削除

では早速追加されている要素を削除する方法を見ていきます。

Listを削除する方法には5通りの方法があります。

  • Removeで要素を削除する方法
  • RemoveAtで要素を削除する方法
  • RemoveRangeで要素を削除する方法
  • RemoveAllで要素を削除する方法
  • Clearで要素を削除する方法

順番に見ていきましょう。

Removeで要素を削除する方法

Removeメソッドでは引数に指定した要素を削除することができます。

public bool Remove(
    T item
)

引数のitemでは、削除する要素を指定します。

ここでいうitemとはそれぞれのListの初期化時に指定した型に対応するものにしましょう。


それでは、サンプルコードで確認していきましょう。

using System;
using System.Collections.Generic;

namespace Sample
{
  class Sample
  {
    static void Main()
    {
      var list = new List<string>();
      list.Add("Tokyo");
      list.Add("Osaka");
      list.Add("Kyoto");

      list.Remove("Osaka");

      Console.WriteLine("[{0}]", string.Join(", ", list));
      Console.ReadKey();
    }
  }
}

実行結果は下のようになります。

[Tokyo, Kyoto]

RemoveAtで要素を削除する方法

Removeメソッドのように要素を直接削除する以外にも、要素の「インデックス番号」で削除したい場合ってありますよね。

そんなときは、RemoveAtメソッドが便利です。
RemoveAtメソッドは以下のように定義されています。

public void RemoveAt(
    int index
)

このように引数Indexでは、削除したい要素の0(ゼロ)から始まるインデックス番号を指定してください。早速サンプルコードで確認してみましょう。

using System;
using System.Collections.Generic;

namespace Sample
{
  class Sample
  {
    static void Main()
    {
      var list = new List<string>();
      list.Add("Tokyo");
      list.Add("Osaka");
      list.Add("Kyoto");

      list.RemoveAt(1);

      Console.WriteLine("[{0}]", string.Join(", ", list));
      Console.ReadKey();
    }
  }
}

これを実行すると

[Tokyo, Kyoto]

となります。

RemoveRangeで要素を削除する方法

次に一度に複数の要素を削除したい場合に使える方法です。
範囲を指定して要素を削除するには、RemoveRangeメソッドを使います。

RemoveRangeメソッドは以下のように定義されています。

public void RemoveRange(
    int index,
    int count
)

引数Indexでは、削除する要素の範囲の「開始位置」をインデックス番号で指定し、引数countでは削除する要素の数を指定してあげます。

サンプルコードで確認しましょう。

using System;
using System.Collections.Generic;

namespace Sample
{
  class Sample
  {
    static void Main()
    {
      var list = new List<string>();
      list.Add("Tokyo");
      list.Add("Osaka");
      list.Add("Kyoto");

      list.RemoveRange(0, 2);

      Console.WriteLine("[{0}]", string.Join(", ", list));
      Console.ReadKey();
    }
  }
}

これを実行してみます。

[Kyoto]

このように0要素目から2要素分が削除されました。

RemoveAllで要素を削除する方法

RemoveRangeでは指定条件を満たす要素を削除することができませんでしたが、そのような場合はRemoveAllメソッドが便利です。

RemoveAllメソッドは以下のように定義されています。

public int RemoveAll(
    Predicate<T> match
)

引数matchでは、削除する要素の条件を定義するデリゲートを指定します。
デリゲートとはC言語の関数ポインタのようなもので、引数matchには削除する条件を定義したメソッド名やラムダ式を指定します。

デリゲートについて詳しく知りたい方は下の記事を参考にしてみてください。

C# 世界一わかるデリゲート(delegate)について

ラムダ式についても解説しているものがあるので、参考にしてみてください。

[C#] ラムダ式はこれさえ見ればOK!簡単徹底解説

では、サンプルコードをご紹介しますね。

using System;
using System.Collections.Generic;

namespace Sample
{
  class Sample
  {
    static void Main()
    {
      var list = new List<string>();
      list.Add("Tokyo");
      list.Add("Osaka");
      list.Add("Kyoto");

      list.RemoveAll(judge);

      Console.WriteLine("[{0}]", string.Join(", ", list));
      Console.ReadKey();
    }

    static bool judge(string s) {
      return s.Contains("a");
    }
  }
}

実行結果:

[Tokyo,Kyoto]

このようになります。
このサンプルコードでは、RemoveAllメソッドを使って要素の文字列に"a"が含まれている場合、その要素を削除するようにしてみました。judgeメソッドで文字列に”a”が含まれているかどうかを判定するように定義しています。

これをラムダ式を使って記述すると以下のようになります。

using System;
using System.Collections.Generic;

namespace Sample
{
  class Sample
  {
    static void Main()
    {
      var list = new List<string>();
      list.Add("Tokyo");
      list.Add("Osaka");
      list.Add("Kyoto");

      list.RemoveAll(s => s.Contains("a"));

      Console.WriteLine("[{0}]", string.Join(", ", list));
      Console.ReadKey();
    }
  }
}

実行結果:

[Tokyo,Kyoto]

結果としては同じですが、記述にラムダ式を使うことで簡潔に書くことができます。

Clearで要素を削除する方法

では最後にListコレクション内の要素をすべて削除する方法をご紹介します。
すべての要素を削除するには"Clear"メソッドを使います。

Clearメソッドの定義はこの様になっています。

public void Clear()

無条件で要素をすべて削除するので引数は特に必要ありません。

実際に使ってみましょう。
下記のサンプルコードを見てください。

using System;
using System.Collections.Generic;
 
namespace Sample
{
  class Sample
  {
    static void Main()
    {
      var list = new List<string>();
      list.Add("Tokyo");
      list.Add("Osaka");
      list.Add("Kyoto");
      
      list.Clear();
      
      Console.WriteLine("[{0}]", string.Join(", ", list));
      Console.ReadKey();
    }
  }
}

実行結果:

[]

すべての要素を削除するので、実行結果はカラになります。

※ Removeとforeachを併用するときには注意

foreachを使って要素に1つずつアクセスし、指定の条件を満たした場合にRemoveメソッドでその要素を削除しようとするとエラーが発生するので注意してください。

サンプルをお見せします。

using System;
using System.Collections.Generic;

namespace Sample
{
  class Sample
  {
    static void Main()
    {
      var list = new List<string>();
      list.Add("Tokyo");
      list.Add("Osaka");
      list.Add("Kyoto");

      foreach(string item in list) {
        if(item.Contains("a")) {
          list.Remove(item);
        }
      }

      Console.WriteLine("[{0}]", string.Join(", ", list));
      Console.ReadKey();
    }
  }
}

上記のように実装してしまうと、

Invalid Operation Exception の例外が発生します。

要素を削除することにより、要素を順に列挙する保証ができなくなってしまうために発生します。

対策としては、

  • forループとRemoveAtメソッドを使ってインデックス番号で要素を指定する
  • RemoveAllメソッドを使う。

上記のどちらかを使用しましょう。

forループとRemoveAtメソッドを使う例をご紹介します。

using System;
using System.Collections.Generic;

namespace Sample
{
  class Sample
  {
    static void Main()
    {
      var list = new List<string>();
      list.Add("Tokyo");
      list.Add("Osaka");
      list.Add("Kyoto");

      for(int i = list.Count - 1; i >= 0; i--) {
        if(list[i].Contains("a")) {
          list.RemoveAt(i);
        }
      }

      Console.WriteLine("[{0}]", string.Join(", ", list));
      Console.ReadKey();
    }
  }
}

実行結果:

[Tokyo,Kyoto]

このサンプルコードでは、forループとRemoveAtメソッドを使って要素を削除しました。
ですが、forループでは要素の末尾からアクセスしています。

なぜそうしているかというと、

要素の先頭からアクセスして削除すると、複数の要素を削除する場合に
削除されない要素が出てくるから

です。

C# Listコレクションのまとめ

C#でよく使うListコレクションの要素を削除する方法を用途別に解説しました。

シンプルに直感的に使えるものですが、組み合わせによってはforeachとRmoveメソッドのように例外が出ることがありますので、注意が必要です。

ループ文について解説している記事もあるので良かったら参考にしてみてください。

[C#] 繰り返し処理(for, while, foreach)について



最近の投稿

Copyright© FUNA BLOG , 2024 All Rights Reserved.