![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi3_komaru-1.png)
C#やVBでもSQLで使えるGroupByを使ってグループ化できたら便利なんだけどできないのかな…?
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi1_normal.png)
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi1_normal.png)
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi1_normal.png)
LINQのGoupByを利用することでグループ化できます。
Select区などを駆使することで.NetでもSQLと似た感覚で利用することができます。
GroupByメソッドとは
リスト内の要素をグループ化するために「GroupBy」メソッドが提供されています。このメソッドを使うことで、同じキーを持つ要素をグループ化して、それぞれのグループを別々のグループに分割することができます。
GroupByメソッドの使い方:コレクション要素をグループ化
LINQのGroupByメソッドを使えば、コレクションの要素をグループ化することができます。 GroupByメソッドを使うと、要素をグループ化した結果を取得することができます。
GroupByメソッドを使うには、まず「System.Linq」名前空間をインポートする必要があります。次に、GroupByメソッドを使用するリストを定義します。このメソッドは、次のような形式で呼び出されます。
var groups = list.GroupBy(x => x.Key);
ここで、「x」はリスト内の要素を表し、「x.Key」はグループ化するキーを表します。グループ化された結果を格納する変数は「groups」としました。
以下のサンプルテーブルを使ってグループ化を行います。
Type | Name | Points |
---|---|---|
食事 | サカナ | 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では匿名型にキーを指定する場合は、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点,武器
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi3_normal-1.png)
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi3_normal-1.png)
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi3_normal-1.png)
GroupByでコレクションのグループ化を行うことができました。
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi1_normal.png)
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi1_normal.png)
![](https://tech.mychma.com/wp-content/uploads/2022/05/hukidashi1_normal.png)
GroupByでグループ化することによってLINQのSelectから合計のSumやカウントをとるCountなどデータベースのSQLと似た感覚で使えるようになります。慣れるととても便利なので使いこなしましょう!
コメント