C# の LINQ で絞り込む Where
Where は LINQ で最も基本的なメソッドだ。条件に合う要素だけを抽出する、いわゆるフィルタリング処理を行う。
基本的な使い方
条件を満たす要素だけを取り出す。
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evenNumbers = numbers.Where(n => n % 2 == 0);
foreach (var n in evenNumbers)
{
Console.WriteLine(n); // 2, 4, 6, 8, 10
}Where にはラムダ式で条件を渡す。この条件を「述語(predicate)」と呼ぶ。述語が true を返した要素だけが結果に含まれる。
オブジェクトのフィルタリング
数値だけでなく、オブジェクトのプロパティで絞り込むことも多い。
var people = new List<Person>
{
new Person { Name = "Alice", Age = 25 },
new Person { Name = "Bob", Age = 30 },
new Person { Name = "Charlie", Age = 35 },
new Person { Name = "Diana", Age = 28 }
};
// 30歳以上の人を抽出
var adults = people.Where(p => p.Age >= 30);
foreach (var person in adults)
{
Console.WriteLine($"{person.Name}: {person.Age}");
}
// Bob: 30
// Charlie: 35プロパティにアクセスして条件を指定できる。複雑なオブジェクトでも同様に扱える。
複数条件の組み合わせ
&& や || で複数の条件を組み合わせられる。
var people = new List<Person>
{
new Person { Name = "Alice", Age = 25, City = "Tokyo" },
new Person { Name = "Bob", Age = 30, City = "Osaka" },
new Person { Name = "Charlie", Age = 35, City = "Tokyo" },
new Person { Name = "Diana", Age = 28, City = "Tokyo" }
};
// 東京在住かつ30歳未満
var result = people.Where(p => p.City == "Tokyo" && p.Age < 30);
foreach (var person in result)
{
Console.WriteLine(person.Name); // Alice, Diana
}論理演算子を使えば、どんな複雑な条件でも表現できる。
Where の連鎖
Where を複数回連鎖させることもできる。
var numbers = Enumerable.Range(1, 100);
var result = numbers
.Where(n => n % 2 == 0) // 偶数
.Where(n => n % 3 == 0) // かつ3の倍数
.Where(n => n > 10); // かつ10より大きい
foreach (var n in result)
{
Console.WriteLine(n); // 12, 18, 24, 30, ...
}これは && で繋いだ一つの Where と同じ結果になる。可読性のために分けることもあるが、通常は一つの Where にまとめた方がシンプルだ。
インデックス付きの Where
要素のインデックスを条件に使いたい場合は、オーバーロードを使う。
string[] fruits = { "apple", "banana", "cherry", "date", "elderberry" };
// インデックスが偶数の要素だけ
var result = fruits.Where((fruit, index) => index % 2 == 0);
foreach (var fruit in result)
{
Console.WriteLine(fruit); // apple, cherry, elderberry
}ラムダ式の第二引数にインデックスが渡される。配列の偶数番目だけを取り出すといった処理に使える。
該当なしの場合
条件に合う要素がない場合、Where は空のシーケンスを返す。例外は発生しない。
int[] numbers = { 1, 2, 3, 4, 5 };
var result = numbers.Where(n => n > 100);
Console.WriteLine(result.Count()); // 0
Console.WriteLine(result.Any()); // False空かどうかは Any() で確認できる。結果を使う前にチェックしておくと安全だ。