存在を忘れがちだがToLookup(またはGroupBy)を使うと1行でできる。
var numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var oddsAndEvens = numbers.ToLookup(n => n % 2 == 0);
// oddsAndEvens[true];
// == [1, 3, 5, 7, 9]
// oddsAndEvens[false];
// == [2, 4, 6, 8, 10]
その他、ありがちなケースとして、「エラーがあるオブジェクトとないオブジェクトを分ける」みたいな時にも使える
var items = new[]
{
new {Name = "A", HasError = false },
new {Name = "B", HasError = true },
new {Name = "C", HasError = false },
new {Name = "D", HasError = true }
};
var validOrInvalidItems = items.ToLookup(i => !i.HasError);
// 指定したキーのデータがなかった時は例外になるので注意
// validOrInvalidItems[false].Select(x => x.Name);
// == ["A", "C"]
// validOrInvalidItems[true].Select(x => x.Name);
// == ["B", "D"]
なお、ToLookupの中身を列挙する場合、今のところ追加した順番が維持されるようだが、保証されている訳ではないと思われるので、列挙する順番が重要な場合はOrderByしてから列挙した方がよさそう。
関連するStackOverflowのQA