バッテラが如く

プログラミングしましょ!

【C#】リスト内の条件に合った要素のインデックスを取得する方法(3選)

3つぐらいやりかたあったのでメモ

for文回して探す方法

int index = -1;
for (int i= 0; i < _params.Count; i++)
{
    /* 条件式 */
    if (_params[i] == ○○) 
    {
        index = i;
        break; 
    }
}

// _params はList型の変数です

どの言語でもできそうなシンプルなやつです。

上記のコードは条件にあった最初のインデックスを返します

最後のインデックスにしたい場合は、break;を消せばOKですね。

見つからない場合は初期化時の値になります。今回のだと-1 ですね

FindIndexを使う方法

int index = _params.FindIndex(x => '条件式');

Listクラス専用のメンバメソッドです。条件にあう最初の要素のインデックスを返します。

見つからない場合は -1 が返ってきます

通常の配列だとこのメソッドがないので使えないので注意が必要ですね。

System.Linqを使う方法

int index = _params.Select((item, index) => new { Index = index, Value = item })
   .Where(x => '条件式')
   .Select(x => x.Index)
   .DefaultIfEmpty(-1)
   .First();

上記コードで他のパターンと同じ結果になります。

1回のメソッドチェーンで済ますにはこうなりました。

:かなり複雑なコードですよね笑。 *

解説はしますが、長いので読み飛ばしてもらってもOKです。

コードの解説

System.Linqは要素の抽出には強いのですがインデックスを見つけるのは苦手なんです。

ListクラスにおけるFindIndexに相当するメソッドが御座いません。

なのでメソッドチェーンで無理くりインデックスを抽出します。

  1. Selectを使ってインデックスと要素の2つを持つ匿名クラスに射影しています。
  2. Whereで条件に合うものだけを抽出します。↑で分解した要素部分で判定しています。
  3. Selectでインデックスだけの配列になるように射影しています。
  4. DefaultIfEmptyで条件にあったものが見つからない場合に要素を1個追加します。今回は -1 という要素を追加しています。
  5. First は複数見つかった場合に最初の要素(インデックス)を返します。

試行錯誤

Firstは例外吐く可能性を秘めているのですがDefaultIfEmptyかますことで要素が0の時がなくなるので例外がでないようになっています。

※配列の要素数が元々0だったとしてもこれで防げます。

元々はFirstではなくFirstOrDefaultを使っていたのですが、これだと見つからない場合にdefault値が返ります。

数値型のdefault値は0になります。

この0が少しやっかいで、配列の0番目が該当したのか、見つからなくて0だったのかが判断つかないからです

といういうのものありFirstOrDefaultだけだとダメということになりました。

default値について公式ページをご参照くださいませ。

docs.microsoft.com