LINQが登場して10年以上が経過しましたが、私の周りには未だに使えない開発者の方が大勢いらっしゃいます。
「ラムダ式がよくわからないので、LINQやラムダ式は使わないでください。」という客先の開発者の方もいます。(年配の方が多いです。)
自分も数年前までは仕事でLINQを使う機会があまりなかったので「必要になったらその都度覚えればいいかな~」ぐらいに思っていましたが、ある日突然覚えようと思ってもなかなか覚えられません。よく使うWhereメソッドやSelectメソッドはそれなりに使えますが、LINQで何ができるのかがわかっていないと、LINQでできるのに別の方法で無駄なコードを書くことになってしまうこともあります。
そこで、LINQの拡張メソッドを少しずつまとめていくことにしました。
目次
はじめに
シーケンスについて
本記事に記載の「シーケンス」とは、配列やリストなどの「順序が定まっており、順番に列挙することが可能なコレクション」のことを指します。
実行方法について
「遅延実行」と記載のあるメソッドは戻り値としてIEnumerable<T>型のオブジェクトを返しますが、メソッドを呼び出した時点では実行(実体化)されません。戻り値のIEnumerable<T>型のオブジェクトに対してforeachで要素を読み出した時点や「即時実行」と記載のあるメソッドを呼び出した時点で実行(実体化)されます。「即時実行」と記載のあるメソッドはIEnumerable<T>型などのシーケンスから、別の型のオブジェクトを実体化して返します。
拡張メソッド一覧
本記事で扱う拡張メソッドは次の通りです。
メソッド名 | 説明 |
---|---|
Aggregate | 要素を集計します。 |
All | 指定した条件をすべての要素が満たしているかどうかを返します。 |
Any | 指定した条件を満たしている要素があるかどうかを返します。 |
AsEnumerable | シーケンスをIEnumerable |
Average | 要素内(リストや配列などのシーケンス)の平均値を返します。 |
Cast | シーケンスを指定した型に変換します。 |
Concat | 2つのシーケンスを連結します。 |
Contains | 指定した値が要素内(リストや配列などのシーケンス)にあるかどうかを返します。 |
Count | 要素数を返します。 |
DefaultIfEmpty | 指定したシーケンス(コレクション)を返します。要素がない場合は既定値を返します。 |
Distinct | リストや配列などのシーケンスから重複を除去した結果を返します。 |
ElementAt | 指定したインデックス位置にある要素を返します。 |
ElementAtOrDefault | 指定したインデックス位置にある要素を返します。要素がない場合は既定値を返します。 |
Empty | 指定した型引数を持つ空のIEnumerableを返します。 |
Except | 2つのシーケンスの差集合を取得します。 |
First | 最初の要素を返します。 |
FirstOrDefault | 最初の要素を返します。要素がない場合は既定値(default |
GroupBy | 指定したキーで要素をグループ化します。 |
GroupJoin | 一致するキーに基づいて2つのシーケンスを関連付け、指定したキーで要素をグループ化します。 |
Intersect | 2つのシーケンスの積集合を取得します。 |
Join | 一致するキーに基づいて2つのシーケンスを関連付けます。 |
Last | 最後の要素を返します。 |
LastOrDefault | 最後の要素を返します。要素がない場合は既定値を返します。 |
LongCount | 要素数をlong(64ビット符号付き整数)で返します。 |
Max | 要素内(リストや配列などのシーケンス)の最大値を返します。 |
Min | 要素内(リストや配列などのシーケンス)の最小値を返します。 |
OfType | 指定した型に変換できる要素を返します。 |
OrderBy | 要素を昇順に並べ替えます。 |
OrderByDescending | 要素を降順に並べ替えます。 |
Range | 指定した値から1ずつインクリメント(増量)しながら、指定した回数分繰り返した整数のシーケンスを作成します。 |
Repeat | 指定した値を、指定した回数分繰り返したシーケンスを作成します。 |
Reverse | 要素の順番を逆転させます。 |
Select | 新しいシーケンス(コレクション)を作成します。 |
SelectMany | Selectメソッドで2次元で返されるコレクションを1次元のコレクションで返します。(平坦化して返します。) |
SequenceEqual | 要素が同じかどうかを返します。 |
Single | 唯一の要素を返します。要素が複数になる場合は例外をスローします。 |
SingleOrDefault | 唯一の要素を返します。要素がない場合は既定値を返します。 |
Skip | 指定した個数の要素を飛ばした残りの要素を返します。 |
SkipWhile | 指定した条件を満たす間は要素を飛ばした残りの要素を返します。 |
Sum | 要素の合計値を返します。 |
Take | 先頭から指定した個数の要素を返します。 |
TakeWhile | 先頭から指定した条件を満たす間の要素を返します。 |
ThenBy | OrderByの結果を維持したままシーケンスの要素を昇順に並び替えます。 |
ThenByDescending | OrderByの結果を維持したままシーケンスの要素を降順に並び替えます。 |
ToArray | シーケンスを配列に変換します。 |
ToDictionary | シーケンスをDictionary |
ToList | シーケンスをList |
ToLookup | 指定したキーごとに要素をまとめます。 |
Union | 2つのシーケンスの和集合を取得します。 |
Where | 指定した条件に一致する要素を返します。 |
Zip | 2つのシーケンスをマージします。 |
要素を取得する
要素を取得するメソッドは次の14メソッドになります。
メソッド名 | 実行方法 |
---|---|
Where | 遅延実行 |
Take | 遅延実行 |
TakeWhile | 遅延実行 |
Skip | 遅延実行 |
SkipWhile | 遅延実行 |
First | 即時実行 |
FirstOrDefault | 即時実行 |
Last | 即時実行 |
LastOrDefault | 即時実行 |
ElementAt | 即時実行 |
ElementAtOrDefault | 即時実行 |
Single | 即時実行 |
SingleOrDefault | 即時実行 |
DefaultIfEmpty | 即時実行 |
Where
遅延実行
Whereメソッドは指定した条件に一致する要素を返します。
1 2 3 |
var numbers = new List<int> { 0, 5, 10, 15, 20, 25, 30 }; // 15以上の要素を取得する var query = numbers.Where(x => x >= 15); |
実行結果として15, 20, 25, 30を返します。
Take
遅延実行
Takeメソッドは先頭から指定した個数の要素を返します。
1 2 3 |
var numbers = Enumerable.Range(1, 9); // 先頭から3つの要素を取得する var query = numbers.Take(3); |
実行結果として1, 2, 3を返します。
TakeWhile
遅延実行
TakeWhileメソッドは先頭から指定した条件を満たす間の要素を返します。
1 2 3 |
var numbers = new int[] { 3, 2, 10, 6, 1 }; // 5未満の間の要素を取得する var query = numbers.TakeWhile(x => x < 5); |
実行結果として3, 2を返します。
Skip
遅延実行
Skipメソッドは指定した個数の要素を飛ばした残りの要素を返します。
1 2 3 |
var numbers = new List<int> { 16, 3, 15, 32, 5, 22, 7 }; // 3つの要素を飛ばした残りの要素を取得する var query = numbers.Skip(3); |
実行結果として32, 5, 22, 7を返します。
SkipWhile
遅延実行
SkipWhileメソッドは指定した条件を満たす間は要素を飛ばした残りの要素を返します。
1 2 3 |
var numbers = new List<int> { 0, 5, 10, 15, 20, 3, 12 }; // 20未満の要素を飛ばした残りの要素を取得する var query = numbers.SkipWhile(x => x < 20); |
実行結果として20, 3, 12を返します。
First
即時実行
Fiestメソッドは最初の要素を返します。
1 2 3 4 5 |
var numbers = new[] { 6, 15, 3, 4, 25 }; // 最初の要素を取得する var query1 = numbers.First(); // 6未満の最初の要素を取得する var query2 = numbers.First(x => x < 6); |
実行結果としてquery1には6を返します。query2には3を返します。
FirstOrDefault
即時実行
FirstOrDefaultメソッドは最初の要素を返します。要素がない場合は既定値(default<T>)を返します。
1 2 3 4 5 6 7 |
var numbers1 = new int[] { }; // 最初の要素を取得する var query1 = numbers1.FirstOrDefault(); var numbers2 = new[] { 26, 15, 36, 24, 7 }; // 10未満の最初の要素を取得する var query2 = numbers2.FirstOrDefault(x => x < 10); |
実行結果としてquery1には0を返します。query2には7を返します。
Last
即時実行
Lastメソッドは最後の要素を返します。
1 2 3 4 5 |
var numbers = new[] { 6, 15, 3, 4, 25 }; // 最後の要素を取得する var query1 = numbers.Last(); // 6未満の最後の要素を取得する var query2 = numbers.Last(x => x < 6); |
実行結果としてquery1には25を返します。query2には4を返します。
LastOrDefault
即時実行
LastOrDefaultメソッドは最後の要素を返します。要素がない場合は既定値を返します。
1 2 3 4 5 6 7 |
var numbers1 = new int[] { 3, 8, 2 }; // 最後の要素を取得する var query1 = numbers1.LastOrDefault(); var numbers2 = new[] { 26, 15, 36, 24, 17 }; // 10未満の最後の要素を取得する var query2 = numbers2.LastOrDefault(x => x < 10); |
実行結果としてquery1には2を返します。query2には0を返します。
ElementAt
即時実行
ElementAtメソッドは指定したインデックス位置にある要素を返します。
1 2 3 |
var text = "aiueo"; // インデックスが3の位置にある要素を取得する var query = text.ElementAt(3); |
実行結果としてeを返します。
ElementAtOrDefault
即時実行
ElementAtOrDefaultメソッドは指定したインデックス位置にある要素を返します。要素がない場合は既定値を返します。
1 2 3 |
var numbers = new int[] { 3, 8, 2, 10 }; // インデックスが4の位置にある要素を取得する var query = numbers.ElementAtOrDefault(4); |
実行結果として0を返します。
Single
即時実行
Singleメソッドは唯一の要素を返します。要素が複数になる場合は例外をスローします。
1 2 3 4 5 |
var numbers = new List<int> { 34, 81, 2, 50, 34 }; // 唯一の要素を取得する var query1 = numbers.Single(); // 34未満の唯一の要素を取得する var query2 = numbers.Single(x => x < 34); |
実行結果としてquery1は例外が発生します。query2は2を返します。
SingleOrDefault
即時実行
SingleOrDefaultメソッドは唯一の要素を返します。要素がない場合は既定値を返します。
1 2 3 |
var numbers = new int[] { 3, 8, 2, 10 }; // 9以上の唯一の要素を取得する var query = numbers.SingleOrDefault(x => x >= 9); |
実行結果として10を返します。
DefaultIfEmpty
即時実行
DefaultIfEmptyメソッドは指定したシーケンス(コレクション)を返します。要素がない場合は既定値を返します。
1 2 3 4 5 6 7 8 |
var numbers1 = new int[] { 1, 3, 5 }; var numbers2 = new int[] {}; // 要素を取得 var query1 = numbers1.DefaultIfEmpty(); var query2 = numbers2.DefaultIfEmpty(); // 空の場合の既定値を指定して要素を取得 var query3 = numbers1.DefaultIfEmpty(-1); var query4 = numbers2.DefaultIfEmpty(-1); |
実行結果としてquery1には「1, 3, 5」を返します。query2には「0」を返します。query3には「1, 3, 5」を返します。query4には「-1」を返します。
新しい要素のシーケンス(コレクション)を作成する(射影)
新しい要素のシーケンス作成する(要素を射影する)メソッドは次の2メソッドになります。
メソッド名 | 実行方法 |
---|---|
Select | 遅延実行 |
SelectMany | 遅延実行 |
使用するクラスとオブジェクト
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public class Person { public string Name { get; set; } public int Age { get; set; } public IEnumerable<Tool> Tools { get; set; } } public class Tool { public string Name { get; set; } } private List<Person> people = new List<Person> { new Person { Name = "John", Age = 15, Tools = new List<Tool> { new Tool { Name = "John's Tool1" }, new Tool { Name = "John's Tool2" }, } }, new Person { Name = "Bob", Age = 17, Tools = new List<Tool> { new Tool { Name = "Bob's Tool1" }, new Tool { Name = "Bob's Tool2" }, } }, }; |
Select
遅延実行
Selectメソッドは新しいシーケンス(コレクション)を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public void Select() { // Ageのみ取得 var query1 = people.Select(p => p.Age); // Ageを2倍にして取得 var query2 = people.Select(p => p.Age * 2); // NameをNamae、AgeをNenrei(匿名型)として取得 var query3 = people.Select(p => new { Namae = p.Name, Nenrei = p.Age }); // Toolsのみ取得 var query4 = people.Select(p => p.Tools); // Toolsの取り出し foreach (IEnumerable<Tool> q in query4) { // JohnとBobのToolsがquery4に返るのでそれぞれを再度ループしてToolを取り出す foreach (Tool t in q) { // 2つのループでToolを取得 string name = t.Name; } } } |
実行結果としてquery1には15, 17を返します。query2には30, 34を返します。
query3には匿名オブジェクトとして
{
Namae = “John”, Nenrei = 15
Namae = “Bob”, Nenrei = 17
}
を返します。
query4にはToolsを返しますがIEnumerable<Tool>型が返るので、Toolを取り出すのに2つのループが必要です。(JohnとBobのそれぞれのToolsが返ります。)
SelectMany
遅延実行
SelectManyメソッドはSelectメソッドで2次元で返されるコレクションを1次元のコレクションで返します。(平坦化して返します。)
1 2 3 4 5 6 7 8 9 10 11 |
public void SelectMany() { // Toolsのみ取得 var query = people.SelectMany(p => p.Tools); // Toolsの取り出し foreach (Tool t in query) { // 1つのループでToolを取得 string name = t.Name; } } |
実行結果として”John’s Tool1″, “John’s Tool2”, “Bob’s Tool1”, “Bob’s Tool2″の4要素を返します。(queryに4要素が返ります。)
重複する要素を除去する
重複する要素を除去するメソッドはDistinctになります。
メソッド名 | 実行方法 |
---|---|
Distinct | 遅延実行 |
Distinct
遅延実行
Distinctメソッドはリストや配列などのシーケンスから重複を除去した結果を返します。
1 2 3 |
var numbers = new int[] { 1, 4, 5, 1, 3, 2, 4 }; // 要素を降順に並べ替える var query = numbers.Distinct(); |
実行結果として「1, 4, 5, 3, 2」を返します。
要素内(リストや配列などのシーケンス)で計算する
要素内(リストや配列などのシーケンス)で計算するメソッドは次の7メソッドになります。
メソッド名 | 実行方法 |
---|---|
Average | 即時実行 |
Sum | 即時実行 |
Aggregate | 即時実行 |
Count | 即時実行 |
LongCount | 即時実行 |
Max | 即時実行 |
Min | 即時実行 |
Average
即時実行
Averageメソッドは要素内(リストや配列などのシーケンス)の平均値を返します。
1 2 3 |
var numbers = new int[] { 80, 75, 62, 87 }; // 全要素の平均値を取得 var query = numbers.Average(); |
実行結果として76を返します。
Sum
即時実行
Sumメソッドは要素の合計値を返します。
1 2 3 |
var numbers = new int[] { 71, 87, 80, 66 }; // 全要素の合計値を取得 var query = numbers.Sum(); |
実行結果として304を返します。
Aggregate
即時実行
Aggregateメソッドは要素を集計します。
1 2 3 |
var numbers = new int[] { 1, 3, 7, 5 }; // 全要素を集計して合計値を取得 var query1 = numbers.Aggregate((total, next) => total += next); |
// 全要素を集計して最大値を取得
var query2 = numbers.Aggregate((greaterthan, next) => greaterthan < next ? next : greaterthan);
実行結果としてquery1には16を返します。query2には7を返します。
Count
即時実行
Countメソッドは要素数を返します。
1 2 3 |
var numbers = new int[] { 1, 2, 3, 4, 5 }; // 全要素の要素数を取得 var query = numbers.Count(x => x < 4); |
実行結果として3を返します。
LongCount
即時実行
LongCountメソッドは要素数をlong(64ビット符号付き整数)で返します。
1 2 3 |
var numbers = new int[] { 1, 2, 3, 4, 5 }; // 全要素の要素数を取得 var query = numbers.LongCount(); |
実行結果として5を返します。
Max
即時実行
Maxメソッドは要素内(リストや配列などのシーケンス)の最大値を返します。
1 2 3 |
var numbers = new int[] { 3, 9, 6, 4, 2 }; // 全要素の最大値を取得 var query = numbers.Max(); |
実行結果として9を返します。
Min
即時実行
Minメソッドは要素内(リストや配列などのシーケンス)の最小値を返します。
1 2 3 |
var numbers = new int[] { 3, 9, 6, 4, 2 }; // 全要素の最小値を取得 var query = numbers.Min(); |
実行結果として2を返します。
要素を判定・検証する
要素を判定・検証するメソッドは次の4メソッドになります。
メソッド名 | 実行方法 |
---|---|
All | 即時実行 |
Any | 即時実行 |
Contains | 即時実行 |
SequenceEqual | 即時実行 |
All
即時実行
Allメソッドは指定した条件をすべての要素が満たしているかどうかを返します。
1 2 3 4 5 6 7 8 9 10 |
var ninjas = new string[] { "Akakage", "Aokage", "Shirokage" }; // 全要素の末尾が「kage」かどうかを判定する var query1 = ninjas.(shinobi => shinobi.EndsWith("kage")); // 全要素の先頭が「A」かどうかを判定する var query2 = ninjas.All(shinobi => shinobi.StartsWith("A")); |
実行結果としてquery1にはtrueを返します。query2にはfalseを返します。
Any
即時実行
Anyメソッドは指定した条件を満たしている要素があるかどうかを返します。
1 2 3 4 5 6 7 8 |
var ninjas = new string[] { "Akakage", "Aokage", "Shirokage" }; // 先頭が「A」の要素があるかどうかを判定する var query = ninjas.Any(shinobi => shinobi.StartsWith("A")); |
実行結果としてtrueを返します。
Contains
即時実行
Containsメソッドは指定した値が要素内(リストや配列などのシーケンス)にあるかどうかを返します。
1 2 3 4 5 6 7 8 9 10 11 12 |
var animals = new string[] { "cow", "horse", "wolf", "lion", "bear", "zebra", "tiger" }; // 要素内に「wolf」があるかどうかを検証する var query = animals.Contains("wolf"); |
実行結果としてtrueを返します。
SequenceEqual
即時実行
SequenceEqualメソッドは要素が同じかどうかを返します。
1 2 3 4 5 6 |
var numbers1 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }; var numbers2 = new int[] { 0, 1, 2, 3, 5, 4, 6, 7 }; var numbers3 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }; // 要素が同じかどうかを判定する var query1 = numbers3.(numbers1); var query2 = numbers3.(numbers2); |
実行結果としてquery1にはtrueを返します。query2にはfalseを返します。
シーケンス(リストや配列などの要素の集まり)を変換する
シーケンス(リストや配列などの要素の集まり)を変換するメソッドは次の6メソッドになります。
メソッド名 | 実行方法 |
---|---|
ToArray | 即時実行 |
ToList | 即時実行 |
ToDictionary | 即時実行 |
AsEnumerable | 遅延実行 |
Cast | 遅延実行 |
OfType | 遅延実行 |
ToArray
即時実行
ToArrayメソッドはシーケンスを配列に変換します。
1 2 3 |
var numbers = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7 }; // 配列に変換する var query = numbers.ToArray(); |
実行結果としてint[]を返します。
ToList
即時実行
ToListメソッドはシーケンスをList<T>に変換します。
1 2 3 |
var numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }; // Listに変換する var query = numbers.ToList(); |
実行結果としてList<int>を返します。
ToDictionary
即時実行
ToDictionaryメソッドはシーケンスをDictionary<TKey,TValue>に変換します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
private class Person { public string Name { get; set; } public int Age { get; set; } } private void ToDictionary() { var person1 = new Person { Name = "Taro", Age = 20 }; var person2 = new Person { Name = "Ichiro", Age = 19 }; var person3 = new Person { Name = "Jiro", Age = 17 }; // Dictionaryに変換する var perple = new List<Person>() { person1, person2, person3 }; // Nameをキーに指定 var query = perple.ToDictionary(person => person.Name); } |
実行結果としてDictionary<string, Person>を返します。
AsEnumerable
遅延実行
AsEnumerableメソッドはシーケンスをIEnumerable<T>に変換します。
1 2 3 |
var numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }; // IEnumerableに変換する var query = numbers.AsEnumerable(); |
実行結果としてIEnumerable<int>を返します。
Cast
遅延実行
Castメソッドはシーケンスを指定した型に変換します。
1 2 3 |
var numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }; // 10 進数型(decimal)に変換する var query = numbers.Cast<decimal>(); |
実行結果としてIEnumerable<decimal>を返します。
OfType
遅延実行
OfTypeメソッドは指定した型に変換できる要素を返します。
1 2 3 4 5 6 7 8 9 10 |
var list = new System.Collections.ArrayList() { "cat", 5.2, "dog", "rabbit", 123456 }; // 文字列型(string)に変換可能な要素を取得 var query = list.OfType<string>(); |
実行結果として「”cat”, “dog”, “rabbit”」を返します。
シーケンス(リストや配列などの要素の集まり)を結合する
シーケンス(リストや配列などの要素の集まり)を結合するメソッドは次の3メソッドになります。
メソッド名 | 実行方法 |
---|---|
Concat | 遅延実行 |
Join | 遅延実行 |
Zip | 遅延実行 |
Concat
遅延実行
Concatメソッドは2つのシーケンスを連結します。(縦結合)
1 2 3 4 |
var numbers1 = new int[] { 0, 2, 4, 6, 8 }; var numbers2 = new int[] { 1, 3, 5, 7, 9 }; // numbers1の要素の後にnumbers2の要素を連結する var query = numbers1.Concat(numbers2); |
実行結果として「0, 2, 4, 6, 8, 1, 3, 5, 7, 9」を返します。
Join
遅延実行
Joinメソッドは一致するキーに基づいて2つのシーケンスを関連付けます。(横結合)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
private class Person { public string Name { get; set; } public string Gender { get; set; } } private class Gender { public string Code { get; set; } public string Name { get; set; } } private void Join() { var genders = new Gender[] { new Gender{ Code="M", Name="Man" }, new Gender{ Code="W", Name="Woman" } }; var people = new Person[] { new Person{ Name = "George", Gender = "M" }, new Person{ Name = "Jane", Gender = "W" }, new Person{ Name = "Catherine", Gender = "W" }, new Person{ Name = "Chris", Gender = "M" }, }; // peopleとgendersを関連付ける var query = people.Join( genders, person => person.Gender, gender => gender.Code, (person, gender) => new { person.Name, Gender = gender.Name}); foreach (var person in query) { Console.WriteLine($"Name: {person.Name} Gender: {person.Gender}"); } } /* Name: George Gender: Man Name: Jane Gender: Woman Name: Catherine Gender: Woman Name: Chris Gender: Man */ |
実行結果としてName (Person.Name)とGender (Gender.Name)を持つオブジェクトを返します。
Zip
遅延実行
Zipメソッドは2つのシーケンスをマージします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
int[] numbers = new int[] { 1, 2, 3, 4 }; string[] texts = new string[] { "A", "B", "C", "D", "E" }; // numbersとtextsをマージする var query = numbers.Zip( texts, (number, text) => new { Number = number, Text = text}); foreach (var item in query) { Console.WriteLine($"Number: {item.Number} Text: {item.Text}"); } /* Number: 1 Text: A Number: 2 Text: B Number: 3 Text: C Number: 4 Text: D */ |
実行結果としてマージできた要素を返します。
要素をグループ化する(グルーピング)
要素をグループ化するメソッドは次の2メソッドになります。
メソッド名 | 実行方法 |
---|---|
GroupBy | 遅延実行 |
ToLookup | 即時実行 |
GroupBy
遅延実行
GroupByメソッドは指定したキーで要素をグループ化します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
private class Student { public string Name { get; set; } public int Age { get; set; } public string Group { get; set; } } private void GroupBy() { var students = new Student[] { new Student { Name="John", Age=14, Group="B" }, new Student { Name="Nancy", Age=14, Group="A" }, new Student { Name="Bob", Age=15, Group="A" }, new Student { Name="Steve", Age=14, Group="C" }, new Student { Name="Yuko", Age=15, Group="B" }, new Student { Name="Cammy", Age=15, Group="C" } }; // Groupプロパティの値でグループ化 var query = students.GroupBy(student => student.Group); // queryはIEnumerable<IGrouping<string, Student>>型 foreach (var group in query) { Console.WriteLine($"Group: {group.Key}"); foreach (var student in group) { Console.WriteLine($" Name: {student.Name} Age: {student.Age}"); } } } /* Group: B Name: John Age: 14 Name: Yuko Age: 15 Group: A Name: Nancy Age: 14 Name: Bob Age: 15 Group: C Name: Steve Age: 14 Name: Cammy Age: 15 */ |
実行結果としてIEnumerable<IGrouping<string, Student>>を返します。
ToLookup
即時実行
ToLookupメソッドは指定したキーごとに要素をまとめます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
private class Member { public string Name { get; set; } public int Age { get; set; } public string Team { get; set; } } private void ToLookup() { var members = new Member[] { new Member { Name="Tom", Age=14, Team="C" }, new Member { Name="Natalie", Age=14, Team="A" }, new Member { Name="Emma", Age=15, Team="B" }, new Member { Name="Ken", Age=14, Team="B" }, new Member { Name="Milla", Age=15, Team="C" }, new Member { Name="Jackie", Age=15, Team="A" } }; // Teamプロパティの値ごとにまとめる var query = members.ToLookup(member => member.Team); // queryはILookup<string, Member>型 foreach (var team in query) { Console.WriteLine($"Team: {team.Key}"); foreach (var member in team) { Console.WriteLine($" Name: {member.Name} Age: {member.Age}"); } } } /* Team: C Name: Tom Age: 14 Name: Milla Age: 15 Team: A Name: Natalie Age: 14 Name: Jackie Age: 15 Team: B Name: Emma Age: 15 Name: Ken Age: 14 */ |
実行結果としてILookup<string, Member>を返します。
シーケンス(リストや配列などの要素の集まり)を結合して要素をグループ化する
シーケンス(リストや配列などの要素の集まり)を結合して要素をグループ化するメソッドはGroupJoinになります。
メソッド名 | 実行方法 |
---|---|
GroupJoin | 遅延実行 |
GroupJoin
遅延実行
GroupJoinメソッドは一致するキーに基づいて2つのシーケンスを関連付け、指定したキーで要素をグループ化します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
private class Member { public string Name { get; set; } public string Team { get; set; } } private class Team { public string Code { get; set; } public string Name { get; set; } } private class GroupElement { public string TeamCode { get; set; } public string TeamName { get; set; } public Member[] Members { get; set; } } private void GroupJoin() { var teams = new Team[] { new Team { Code = "A", Name = "A team" }, new Team { Code = "B", Name = "B team" }, }; var members = new Member[] { new Member { Name = "John ", Team="A" }, new Member { Name = "Paul ", Team="B" }, new Member { Name = "George", Team="A" }, new Member { Name = "Ringo", Team="B" } }; // Teamで結合してグループ化 var query = teams.GroupJoin( members, team => team.Code, member => member.Team, (team, memberList) => new GroupElement { TeamCode = team.Code, TeamName = team.Name, Members = memberList.ToArray() }); foreach (var group in query) { Console.WriteLine($"TeamCode: {group.TeamCode} TeamName: {group.TeamName}"); foreach (var member in group.Members) { Console.WriteLine($" {member.Name}"); } } } /* TeamCode: A TeamName: A team John George TeamCode: B TeamName: B team Paul Ringo */ |
実行結果としてGroupElementのコレクションを返します。
要素を並べ替える
要素を検証・判定するメソッドは次の5メソッドになります。
メソッド名 | 実行方法 |
---|---|
Reverse | 遅延実行 |
OrderBy | 遅延実行 |
OrderByDescending | 遅延実行 |
ThenBy | 遅延実行 |
ThenByDescending | 遅延実行 |
Reverse
遅延実行
Reverseメソッドは要素の順番を逆転させます。
1 2 3 |
var chars = new char[] { 'a', 'b', 'c', 'd', 'e' } // 要素の順番を逆転させる var query = chars.Reverse(); |
実行結果として「e, d, c, b, a」を返します。
OrderBy
遅延実行
OrderByメソッドは要素を昇順に並べ替えます。
1 2 3 |
var numbers = new int[] { 0, 3, 5, 1, 4, 2 }; // 要素を昇順に並べ替える var query = numbers.OrderBy(number => number); |
実行結果として「0, 1, 2, 3, 4, 5」を返します。
OrderByDescending
遅延実行
OrderByDescendingメソッドは要素を降順に並べ替えます。
1 2 3 |
var numbers = new int[] { 0, 3, 5, 1, 4, 2 }; // 要素を降順に並べ替える var query = numbers.OrderByDescending(number => number); |
実行結果として「5, 4, 3, 2, 1, 0」を返します。
ThenBy
遅延実行
ThenByメソッドはOrderByの結果を維持したままシーケンスの要素を昇順に並び替えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var animals = new string[] { "horse", "cow", "lion", "wolf", "bear", "zebra", "tiger" }; // 要素を文字数の昇順に並べ替える var query = animals.OrderBy(animal => animal.Length); // OrderByの結果を保持したまま値の昇順に並べ替える query = query.ThenBy(animal => animal); |
実行結果として「cow, bear, lion, wolf, horse, tiger, zebra」を返します。
ThenByDescending
遅延実行
ThenByDescendingメソッドはOrderByの結果を維持したままシーケンスの要素を降順に並び替えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var animals = new string[] { "horse", "cow", "lion", "wolf", "bear", "tiger", "zebra" }; // 要素を文字数の昇順に並べ替える var query = animals.OrderBy(animal => animal.Length); // OrderByの結果を保持したまま値の降順に並べ替える query = query.ThenByDescending(animal => animal); |
実行結果として「cow, wolf, lion, bear, zebra, tiger, horse」を返します。
シーケンス(リストや配列などの要素の集まり)の集合を演算する
シーケンス(リストや配列などの要素の集まり)の集合を演算するメソッドは次の3メソッドになります。
メソッド名 | 実行方法 |
---|---|
Union | 遅延実行 |
Except | 遅延実行 |
Intersect | 遅延実行 |
Union
遅延実行
Unionメソッドは2つのシーケンスの和集合を取得します。
1 2 3 4 |
var numbers1 = new int[] { 2, 4, 5, 6, 8 }; var numbers2 = new int[] { 1, 3, 5, 7, 8, 9 }; // numbers1とnumbers2の和集合を求める var query = numbers1.Concat(numbers2); |
実行結果として「2, 4, 5, 6, 8, 1, 3, 7, 9」(重複を除いてnumbers1とnumbers2を連結した結果)を返します。
Except
遅延実行
Exceptメソッドは2つのシーケンスの差集合を取得します。
1 2 3 4 |
var numbers1 = new int[] { 2, 4, 5, 6, 8 }; var numbers2 = new int[] { 1, 3, 5, 7, 8, 9 }; // numbers1とnumbers2の差集合を求める var query = numbers1.Except(numbers2); |
実行結果として「2, 4, 6」(numbers1のうちnumbers2に存在しない要素)を返します。
Intersect
遅延実行
Intersectメソッドは2つのシーケンスの積集合を取得します。
1 2 3 4 |
var numbers1 = new int[] { 2, 4, 5, 6, 8 }; var numbers2 = new int[] { 1, 3, 5, 7, 8, 9 }; // numbers1とnumbers2の積集合を求める var query = numbers1.Intersect(numbers2); |
実行結果としてを返します。
実行結果として「5, 8」(numbers1とnumbers2の両方に存在する要素)を返します。
シーケンスを作成する
シーケンスを作成するメソッドは次の3メソッドになります。
メソッド名 | 実行方法 |
---|---|
Range | 遅延実行 |
Repeat | 遅延実行 |
Empty | 遅延実行 |
Range
遅延実行
Rangeメソッドは指定した値から1ずつインクリメント(増量)しながら、指定した回数分繰り返した整数のシーケンスを作成します。
1 2 3 4 5 6 |
private void Range() { var start = 1; var count = 9; var query = Enumerable.Range(start, count); } |
実行結果として「1, 2, 3, 4, 5, 6, 7, 8, 9」を返します。
Repeat
遅延実行
Repeatメソッドは指定した値を、指定した回数分繰り返したシーケンスを作成します。
1 2 3 4 5 6 |
private void Repeat() { var element = 55; var count = 5; var query = Enumerable.Repeat(element, count); } |
実行結果として「55, 55, 55, 55, 55」を返します。
Empty
遅延実行
Emptyメソッドは指定した型引数を持つ空のIEnumerable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
private class Person { public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; } } private void Empty() { // stringのコレクションを作成 var strings = Enumerable.Empty<string>(); // Personのコレクションを作成 var people = Enumerable.Empty<Person>(); } |
実行結果としてstringsには空のstringのコレクションを返します。peopleには空のPersonのコレクションを返します。
参考: Enumerable クラス