C#には LINQ というライブラリがあります。
LINQ を使えばコレクション(配列や List クラスなど)に対する処理を簡単に行う事が出来ます。
ここでは、LINQ を使って配列をグループ毎にまとめて処理する方法について解説します。
LINQとは
LINQ は IEnumerable<T>インターフェースへの拡張メソッドとして作られています。
つまり、配列、Listクラス、Dictionaryクラス、ObservableCollectionクラスなどのIEnumerable<T>インターフェースを実装するオブジェクトであればどれでも同じように使用する事ができます。
LINQをつかうには using で System.Linq を参照できるようにしておきましょう。
using System.Linq;
配列をグループ化する GroupByメソッド
配列をグループ化するには GroupBy メソッドを使用します。
引数にグループ化のキーとする値を指定しますが、ラムダ式を使って記述するのが簡単で一般的な方法です。
※ラムダ式の詳細は「C#のラムダ式【=>】って何?」をご覧ください
以下の例ではCategoryでグループ化してそれそれのPointの平均を求めています。
TestItem[] testArray = new TestItem[6]; testArray[0] = new TestItem() { Class = "A", Author = "太郎", Category = "国語", Point = 50 }; testArray[1] = new TestItem() { Class = "A", Author = "太郎", Category = "算数", Point = 70 }; testArray[2] = new TestItem() { Class = "A", Author = "次郎", Category = "国語", Point = 90 }; testArray[3] = new TestItem() { Class = "A", Author = "次郎", Category = "算数", Point = 10 }; testArray[4] = new TestItem() { Class = "B", Author = "三郎", Category = "国語", Point = 60 }; testArray[5] = new TestItem() { Class = "B", Author = "三郎", Category = "算数", Point = 60 }; IEnumerable<IGrouping<string, TestItem>> testGroup = testArray.GroupBy(o => o.Category); foreach (IGrouping<string, TestItem> group in testGroup) { int total = 0; foreach (TestItem item in group) { total += item.Point; } Console.WriteLine("Category=" + group.Key + " Average=" + (total / group.Count())); }
複数の値をキーにしてグループ化
複数の値をキーにしたい場合、ラムダ式でキーとなる値を複数返す必要があります。
この場合、匿名クラスを利用するのが良さそうです。
Point[] testArray = new Point[5]; testArray[0] = new Point(4, 5); testArray[1] = new Point(2, 6); testArray[2] = new Point(1, 6); testArray[3] = new Point(4, 2); testArray[4] = new Point(6, 3); var testGroup = testArray.GroupBy(o => new { Class = o.Class, Category = o.Category}); foreach (var group in testGroup) { int total = 0; foreach (TestItem item in group) { total += item.Point; } Console.WriteLine("Class=" + group.Key.Class + "Category=" + group.Key.Category + " Average=" + (total / group.Count())); }
ラムダ式の中で「new { ・・・ }」となっている部分が匿名クラスです。
「Class」と「Category」というメンバ変数を持った名前の無いクラスを作成して、それをラムダ式の戻り値としています。
関連記事
- C#の値型と参照型の違い
- C#のコンストラクタでオーバーロード
- C#のコンストラクタの継承
- C#のジェネリックを使おう
- C#のデリゲート (delegate) って何?
- C#のデリゲートお手軽にする匿名メソッド
- C#のラムダ式【=>】って何?
- C#で基底クラスのメソッドを置き換えるオーバーライド
- C#でキャストとas演算子を使いこなす
- C#で型を判別するtypeofとis演算子
- C#の値型でもnullを扱えるようにするNullable
- C#のリソース解放にはIDisposableとusingを使おう
- C#のStringとstring、Int32とint 違いは・・・ない!
- C#でasync/awaitを使った非同期処理
- C#で文字列を指定の区切り文字で分割
- C#のstring.Formatで桁数や書式を指定する
- C#の配列やListをソートする
- C#の配列やListを検索する (Find,FindAll,FindIndex)
- C#の配列やListを高速に検索する (BinarySearch)
- C#の配列の中に指定の要素が存在するかを調べる(LINQ Contains)
- C#の配列の中に条件を満たす要素が存在するかを調べる(LINQ Any)
- C#の配列から条件に合う要素を抽出する(LINQ Where)
- C#の配列で要素毎の処理結果を得る(LINQ Select)
- C#の配列を並び替える(LINQ OrderBy,ThenBy)
- C#の配列をグループ毎に処理する(LINQ GroupBy)
- C#の配列を内部結合(INNER JOIN)する(LINQ Join)
- C#の配列から最初の要素を取り出す(LINQ First,FirstOrDefault)
- C#の配列の重複要素を削除する(LINQ Distinct)
- C#でフォルダ内のファイル名一覧を取得する
- C#でテキストファイルを読み込む
- C#でテキストファイルに書き込む
- C#でバイナリファイルを読み込む
- C#でバイナリファイルに書き込む
コメントをお書きください