C#/VB.NET LINQのGroupByの使い方:グループ化する方法

C#やVBでもSQLで使えるGroupByを使ってグループ化できたら便利なんだけどできないのかな…?

LINQのGoupByを利用することでグループ化できます。
Select区などを駆使することで.NetでもSQLと似た感覚で利用することができます。

目次

受講者数No.1!初心者からプロへ導く信頼のスクール

    短期間で習得可能!未経験から実践力を磨く充実のプログラム

    今なら無料相談でAmazonギフトカードがもらえる!

    GroupByメソッドとは

     リスト内の要素をグループ化するために「GroupBy」メソッドが提供されています。このメソッドを使うことで、同じキーを持つ要素をグループ化して、それぞれのグループを別々のグループに分割することができます。

    GroupByメソッドの使い方:コレクション要素をグループ化

     LINQのGroupByメソッドを使えば、コレクションの要素をグループ化することができます。 GroupByメソッドを使うと、要素をグループ化した結果を取得することができます。

     GroupByメソッドを使うには、まず「System.Linq」名前空間をインポートする必要があります。次に、GroupByメソッドを使用するリストを定義します。このメソッドは、次のような形式で呼び出されます。

    var groups = list.GroupBy(x => x.Key);

    ここで、「x」はリスト内の要素を表し、「x.Key」はグループ化するキーを表します。グループ化された結果を格納する変数は「groups」としました。

    以下のサンプルテーブルを使ってグループ化を行います。

    TypeNamePoints
    食事サカナ10
    食事サカナ15
    回復やくそう20
    回復どくけし30
    武器40
    サンプルのコレクションイメージ

    単一キーでのグループ化

    以下の例では、アイテムのタイプによってグループ分けを行い、指定したキーごとに出力を行うサンプルです。

    「GroupBy」により、「lstItem」リストの要素を「Type」フィールドの値でグループ分けしています。

     グループ分けされた結果が「query」という変数に格納されます。最後に「query」をforeach文を使って反復処理することで、グループごとに「Type」フィールドの値と「Item」オブジェクトの「Name」「Points」フィールドの値を出力しています。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Diagnostics;
    
    namespace shapetest20221103
    {
        class Item
        {
            public string Type;
            public string Name;
            public int Points;
        }
    
        public partial class Form1 : Form
        {
            public Form1()
            { InitializeComponent(); }
    
            private void button1_Click(object sender, EventArgs e)
            {
                List<Item> lstItem = new List<Item>() { 
                                        new Item { Points =10, Name ="サカナ", Type = "食事"},
                                        new Item { Points =15, Name ="サカナ", Type = "食事"},
                                        new Item { Points =20, Name ="やくそう", Type = "回復"},
                                        new Item { Points =30, Name ="どくけし", Type = "回復"},
                                        new Item { Points =40, Name ="剣", Type = "武器"},
                                        };
    
                var query = lstItem.GroupBy(x => x.Type);
                foreach (var group in query)
                {
                    Debug.Print(group.Key);
                    foreach (var item in group)
                    {
                        Debug.Print("{0}:{1}点", item.Name, item.Points);
                    }
                }
            }
        }
    }
    Public Class Form1
    
    	Class Item
    		Public Type As String
    		Public Name As String
    		Public Points As Integer
    	End Class
    
    	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
    		Dim lstItem As New List(Of Item)() From {
    													New Item() With {
    														.Points = 10,
    														.Name = "サカナ",
    														.Type = "食事"
    													},
    													New Item() With {
    														.Points = 15,
    														.Name = "サカナ",
    														.Type = "食事"
    													},
    													New Item() With {
    														.Points = 20,
    														.Name = "やくそう",
    														.Type = "回復"
    													},
    													New Item() With {
    														.Points = 30,
    														.Name = "どくけし",
    														.Type = "回復"
    													},
    													New Item() With {
    														.Points = 40,
    														.Name = "剣",
    														.Type = "武器"
    													}
    												}
    
    
    		Dim query = lstItem.GroupBy(Function(x) x.Type)
    		For Each group In query
    			Debug.Print(group.Key)
    			For Each item In group
    				Debug.Print("{0}:{1}点", item.Name, item.Points)
    			Next
    		Next
    
    	End Sub
    End Class
    食事
    サカナ:10点
    サカナ:15点
    回復
    やくそう:20点
    どくけし:30点
    武器
    剣:40点

    複数キーでのグループ化

    複数キーでグループ化を行い場合は、GroupBy内にnew区を使って複数のキーを指定します。

     GroupByメソッドは「Type」と「Name」の2つのフィールドをグループのキーとして使用するため、「new { x.Type, x.Name }」という形で複数のキーを指定しています。

    var query = lstItem.GroupBy(x => new { x.Type, x.Name});
    Dim query = lstItem.GroupBy(Function(x) New With { Key x.Type, Key x.Name	})
    VB.NETの場合の注意

    VB.netでは匿名型にキーを指定する場合は、Keyキーワードを付与する必要があります。

    例:lstItem.GroupBy(Function(x) New With {Key x.Type,Key x.Name})

    以下が全体のサンプルプログラムです。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Diagnostics;
    
    namespace shapetest20221103
    {
        class Item
        {
            public string Type;
            public string Name;
            public int Points;
        }
    
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
    
                List<Item> lstItem = new List<Item>() { 
                                        new Item { Points =10, Name ="サカナ", Type = "食事"},
                                        new Item { Points =15, Name ="サカナ", Type = "食事"},
                                        new Item { Points =20, Name ="やくそう", Type = "回復"},
                                        new Item { Points =30, Name ="どくけし", Type = "回復"},
                                        new Item { Points =40, Name ="剣", Type = "武器"},
                                        };
    
                //new区で複数のキーを指定する
                var query = lstItem.GroupBy(x => new { x.Type,
                                                       x.Name});
    
                foreach (var group in query)
                {
                    Debug.Print(group.Key.Name);
                    Debug.Print(group.Key.Type);
    
                    foreach (var item in group)
                    {
                        Debug.Print("{0}:{1}点", item.Name, item.Points);
                        
                    }
                }
            }
        }
    }
    Public Class Form1
    
    	Class Item
    		Public Type As String
    		Public Name As String
    		Public Points As Integer
    	End Class
    
    	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
    		Dim lstItem As New List(Of Item)() From {
    													New Item() With {
    														.Points = 10,
    														.Name = "サカナ",
    														.Type = "食事"
    													},
    													New Item() With {
    														.Points = 15,
    														.Name = "サカナ",
    														.Type = "食事"
    													},
    													New Item() With {
    														.Points = 20,
    														.Name = "やくそう",
    														.Type = "回復"
    													},
    													New Item() With {
    														.Points = 30,
    														.Name = "どくけし",
    														.Type = "回復"
    													},
    													New Item() With {
    														.Points = 40,
    														.Name = "剣",
    														.Type = "武器"
    													}
    												}
    
    
    		'new区で複数のキーを指定する
    		' VB.netでは匿名型にキーを指定する場合は、Keyキーワードを付与する必要があります。
    		Dim query = lstItem.GroupBy(Function(x) New With {
    														 Key x.Type,
    														 Key x.Name
    														})
    
    		For Each group In query
    			Debug.Print(group.Key.Name)
    			Debug.Print(group.Key.Type)
    
    			For Each item In group
    
    				Debug.Print("{0}:{1}点", item.Name, item.Points)
    			Next
    		Next
    
    	End Sub
    End Class
    
    サカナ
    食事
    サカナ:10点
    サカナ:15点
    やくそう
    回復
    やくそう:20点
    どくけし
    回復
    どくけし:30点
    剣
    武器
    剣:40点

    LINQのSelect区を使ってグループごとの点数合計を取得する

     LINQのラムダ式を使用すると、「GroupBy」と「Select」を組み合わせて、分類したグループ内の数値を合計することができます。

    このことを実現するには、「GroupBy」でグループ分けした後、「Select」を使ってグループ内の数値を合計するために「SUM」関数を適用することができます。

    抜粋した例:

                var list = query.Select(x => new
                {
                    Points = x.Sum(x => x.Points),
                    Name = x.Key.Name,
                    Type = x.Key.Type
                }).ToList()
    		'グループごとの合計をLINQのSelect区を使って取得する
    		Dim list = query.Select(Function(x) New With {
    														Key .Points = x.Sum(Function(xx) xx.Points),
    														Key .Name = x.Key.Name,
    														Key .Type = x.Key.Type
    													}).ToList()

    以下が全体のサンプルプログラムです。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Diagnostics;
    
    namespace shapetest20221103
    {
        class Item
        {
            public string Type;
            public string Name;
            public int Points;
        }
    
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
    
                List<Item> lstItem = new List<Item>() { 
                                        new Item { Points =10, Name ="サカナ", Type = "食事"},
                                        new Item { Points =15, Name ="サカナ", Type = "食事"},
                                        new Item { Points =20, Name ="やくそう", Type = "回復"},
                                        new Item { Points =30, Name ="どくけし", Type = "回復"},
                                        new Item { Points =40, Name ="剣", Type = "武器"},
                                        };
    
                //new区で複数のキーを指定する
                var query = lstItem.GroupBy(x => new { x.Type,
                                                       x.Name});
    
                //グループごとの合計をLINQのSelect区を使って取得する
    
                var list = query.Select(x => new
                {
                    Points = x.Sum(x => x.Points),
                    Name = x.Key.Name,
                    Type = x.Key.Type
                }).ToList();
    
                foreach (var it in list)
                {
                    Debug.Print("{0}:{1}点,{2}", it.Name, it.Points,it.Type);
                }
            }
        }
    }
    
    Public Class Form1
    
    	Class Item
    		Public Type As String
    		Public Name As String
    		Public Points As Integer
    	End Class
    
    	Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
    
    		Dim lstItem As New List(Of Item)() From {
    													New Item() With {
    														.Points = 10,
    														.Name = "サカナ",
    														.Type = "食事"
    													},
    													New Item() With {
    														.Points = 15,
    														.Name = "サカナ",
    														.Type = "食事"
    													},
    													New Item() With {
    														.Points = 20,
    														.Name = "やくそう",
    														.Type = "回復"
    													},
    													New Item() With {
    														.Points = 30,
    														.Name = "どくけし",
    														.Type = "回復"
    													},
    													New Item() With {
    														.Points = 40,
    														.Name = "剣",
    														.Type = "武器"
    													}
    												}
    
    		'new区で複数のキーを指定する
    		' VB.netでは匿名型にキーを指定する場合は、Keyキーワードを付与する必要があります。
    		Dim query = lstItem.GroupBy(Function(x) New With {
    														 Key x.Type,
    														 Key x.Name
    														})
    
    		'グループごとの合計をLINQのSelect区を使って取得する
    		Dim list = query.Select(Function(x) New With {
    														Key .Points = x.Sum(Function(xx) xx.Points),
    														Key .Name = x.Key.Name,
    														Key .Type = x.Key.Type
    													}).ToList()
    
    		For Each it In list
    			Debug.Print("{0}:{1}点,{2}", it.Name, it.Points, it.Type)
    		Next
    
    	End Sub
    End Class

    グループ化されているサカナが合計されて統合されています。

    サカナ:25点,食事
    やくそう:20点,回復
    どくけし:30点,回復
    剣:40点,武器

    リスキリングでキャリアアップしてみませんか?

    リスキリング(学び直し)は、経済産業省が推奨しており、

    今だけ、最大70%のキャッシュバックを受けることができます。

    リスキリング 給付金が出るスクール紹介

    最大70%の給付金が出るおすすめのプログラミングスクール!

    国策で予算が決められているため申し込みが多い場合は早期に終了する可能性があります!

    興味のある方はすぐに確認しましょう。

    GroupByでコレクションのグループ化を行うことができました。

    GroupByでグループ化することによってLINQのSelectから合計のSumやカウントをとるCountなどデータベースのSQLと似た感覚で使えるようになります。慣れるととても便利なので使いこなしましょう!

    Microsoft Learnの解説

    よかったらシェアしてね!
    • URLをコピーしました!
    • URLをコピーしました!
    目次