LINQのGroupByメソッドを使用することで、リストを特定のプロパティの値でグループ分けすることができます。
やりたいこと
以下のプロパティを持つProductクラスがあります。
- ID
- 名前(Name)
- カテゴリー(Category)
- 価格(Price)
- 個数(Quantity)
このクラス型の要素を持つproductsに対して、商品のカテゴリー別にグループ分けして、各カテゴリーごとに処理を行いたいです。
今回は以下のように、商品Productの情報をカテゴリーCategoryごとにまとめて表示したいと思います。
【Category : Fruit 】
Id: 1, Name: Apple, Category: Fruit, Price: 120, Quantity: 50
Id: 2, Name: Banana, Category: Fruit, Price: 80, Quantity: 30
Id: 9, Name: Grapes, Category: Fruit, Price: 200, Quantity: 15
Id: 11, Name: Orange, Category: Fruit, Price: 150, Quantity: 35
Id: 16, Name: Strawberry, Category: Fruit, Price: 300, Quantity: 20
Id: 20, Name: Peach, Category: Fruit, Price: 200, Quantity: 30
Id: 22, Name: Mango, Category: Fruit, Price: 250, Quantity: 15
Id: 26, Name: Pineapple, Category: Fruit, Price: 300, Quantity: 10
Id: 30, Name: Melon, Category: Fruit, Price: 180, Quantity: 20
【Category : Vegetable 】
Id: 3, Name: Carrot, Category: Vegetable, Price: 100, Quantity: 20
Id: 4, Name: Tomato, Category: Vegetable, Price: 120, Quantity: 40
Id: 10, Name: Potato, Category: Vegetable, Price: 50, Quantity: 100
Id: 15, Name: Cucumber, Category: Vegetable, Price: 150, Quantity: 25
Id: 17, Name: Lettuce, Category: Vegetable, Price: 90, Quantity: 30
Id: 21, Name: Radish, Category: Vegetable, Price: 70, Quantity: 20
Id: 23, Name: Sweet Corn, Category: Vegetable, Price: 110, Quantity: 40
Id: 27, Name: Spinach, Category: Vegetable, Price: 80, Quantity: 35
【Category : Dairy 】
Id: 5, Name: Milk, Category: Dairy, Price: 180, Quantity: 20
Id: 6, Name: Cheese, Category: Dairy, Price: 300, Quantity: 10
Id: 12, Name: Yogurt, Category: Dairy, Price: 150, Quantity: 20
Id: 13, Name: Ice Cream, Category: Dairy, Price: 300, Quantity: 10
Id: 18, Name: Butter, Category: Dairy, Price: 250, Quantity: 5
Id: 24, Name: Cream, Category: Dairy, Price: 220, Quantity: 10
Id: 28, Name: Whipped Cream, Category: Dairy, Price: 240, Quantity: 10
【Category : Snacks 】
Id: 7, Name: Chips, Category: Snacks, Price: 100, Quantity: 40
Id: 8, Name: Chocolate, Category: Snacks, Price: 250, Quantity: 25
Id: 14, Name: Breadsticks, Category: Snacks, Price: 120, Quantity: 50
Id: 19, Name: Crackers, Category: Snacks, Price: 100, Quantity: 40
Id: 25, Name: Biscuits, Category: Snacks, Price: 130, Quantity: 25
Id: 29, Name: Popcorn, Category: Snacks, Price: 90, Quantity: 50
GroupByを使ってグループ分け
GroupBy()を使うことで、引数で指定したプロパティでリストをグループ分けすることができます。
// カテゴリーCategoryごとにグループ化
var productsGroupedByCategory = products.GroupBy(x => x.Category);
戻り値は「IEnumerable<IGrouping<Key, Element>>」と少し複雑ですが、イメージとしては「各グループのリストを要素として持つリスト」が返ってくる感じになります。
コードで見てみるとわかりやすいと思います。
// カテゴリーごとに商品を表示
foreach (var group in productsGroupedByCategory)
{
// 各グループごとの処理
Console.WriteLine($"【Category : {group.First().Category} 】");
foreach(var product in group)
{
// 1商品の情報を表示
Console.WriteLine($"Id: {product.Id}, Name: {product.Name}, Category: {product.Category}, Price: {product.Price}, Quantity: {product.Quantity}");
}
// ただの改行
Console.WriteLine();
}
まず、外側のforeachです。
GroupBy()の戻り値productsGroupedByCategoryをforeachを使ってグループごとに分割します。これによりforeachの内部では特定のグループのリストgroupが扱えるようになります。
つぎに、内側のforeachです。
特定のグループのリストgroupをforeachを使って分割します。これにより1要素(今回の例では1商品)が扱えるようにします。
コード全体
〇 メインプログラム(エントリポイント)
public class Program
{
static void Main(string[] args)
{
// 商品データの作成
var products = new List<Product>
{
new Product { Id = 1, Name = "Apple", Category = ProductCategory.Fruit, Price = 120, Quantity = 50 },
new Product { Id = 2, Name = "Banana", Category = ProductCategory.Fruit, Price = 80, Quantity = 30 },
new Product { Id = 3, Name = "Carrot", Category = ProductCategory.Vegetable, Price = 100, Quantity = 20 },
new Product { Id = 4, Name = "Tomato", Category = ProductCategory.Vegetable, Price = 120, Quantity = 40 },
new Product { Id = 5, Name = "Milk", Category = ProductCategory.Dairy, Price = 180, Quantity = 20 },
new Product { Id = 6, Name = "Cheese", Category = ProductCategory.Dairy, Price = 300, Quantity = 10 },
new Product { Id = 7, Name = "Chips", Category = ProductCategory.Snacks, Price = 100, Quantity = 40 },
new Product { Id = 8, Name = "Chocolate", Category = ProductCategory.Snacks, Price = 250, Quantity = 25 },
new Product { Id = 9, Name = "Grapes", Category = ProductCategory.Fruit, Price = 200, Quantity = 15 },
new Product { Id = 10, Name = "Potato", Category = ProductCategory.Vegetable, Price = 50, Quantity = 100 },
new Product { Id = 11, Name = "Orange", Category = ProductCategory.Fruit, Price = 150, Quantity = 35 },
new Product { Id = 12, Name = "Yogurt", Category = ProductCategory.Dairy, Price = 150, Quantity = 20 },
new Product { Id = 13, Name = "Ice Cream", Category = ProductCategory.Dairy, Price = 300, Quantity = 10 },
new Product { Id = 14, Name = "Breadsticks", Category = ProductCategory.Snacks, Price = 120, Quantity = 50 },
new Product { Id = 15, Name = "Cucumber", Category = ProductCategory.Vegetable, Price = 150, Quantity = 25 },
new Product { Id = 16, Name = "Strawberry", Category = ProductCategory.Fruit, Price = 300, Quantity = 20 },
new Product { Id = 17, Name = "Lettuce", Category = ProductCategory.Vegetable, Price = 90, Quantity = 30 },
new Product { Id = 18, Name = "Butter", Category = ProductCategory.Dairy, Price = 250, Quantity = 5 },
new Product { Id = 19, Name = "Crackers", Category = ProductCategory.Snacks, Price = 100, Quantity = 40 },
new Product { Id = 20, Name = "Peach", Category = ProductCategory.Fruit, Price = 200, Quantity = 30 },
new Product { Id = 21, Name = "Radish", Category = ProductCategory.Vegetable, Price = 70, Quantity = 20 },
new Product { Id = 22, Name = "Mango", Category = ProductCategory.Fruit, Price = 250, Quantity = 15 },
new Product { Id = 23, Name = "Sweet Corn", Category = ProductCategory.Vegetable, Price = 110, Quantity = 40 },
new Product { Id = 24, Name = "Cream", Category = ProductCategory.Dairy, Price = 220, Quantity = 10 },
new Product { Id = 25, Name = "Biscuits", Category = ProductCategory.Snacks, Price = 130, Quantity = 25 },
new Product { Id = 26, Name = "Pineapple", Category = ProductCategory.Fruit, Price = 300, Quantity = 10 },
new Product { Id = 27, Name = "Spinach", Category = ProductCategory.Vegetable, Price = 80, Quantity = 35 },
new Product { Id = 28, Name = "Whipped Cream", Category = ProductCategory.Dairy, Price = 240, Quantity = 10 },
new Product { Id = 29, Name = "Popcorn", Category = ProductCategory.Snacks, Price = 90, Quantity = 50 },
new Product { Id = 30, Name = "Melon", Category = ProductCategory.Fruit, Price = 180, Quantity = 20 }
};
// カテゴリーごとにグループ化
var productsGroupedByCategory = products.GroupBy(x => x.Category);
// カテゴリーごとに商品を表示
foreach (var group in productsGroupedByCategory)
{
// 各グループごとの処理
Console.WriteLine($"【Category : {group.First().Category} 】");
foreach(var product in group)
{
// 1商品の情報を表示
Console.WriteLine($"Id: {product.Id}, Name: {product.Name}, Category: {product.Category}, Price: {product.Price}, Quantity: {product.Quantity}");
}
// ただの改行
Console.WriteLine();
}
}
}
〇 商品クラス
/// <summary>
/// 商品を表します
/// </summary>
public class Product
{
/// <summary>
/// ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 名前
/// </summary>
public string Name { get; set; }
/// <summary>
/// カテゴリー
/// </summary>
public ProductCategory Category { get; set; }
/// <summary>
/// 単価
/// </summary>
public int Price { get; set; }
/// <summary>
/// 在庫数
/// </summary>
public int Quantity { get; set; }
}
〇 カテゴリ列挙
/// <summary>
/// カテゴリーを表します
/// </summary>
public enum ProductCategory
{
/// <summary>
/// 果物
/// </summary>
Fruit,
/// <summary>
/// 野菜
/// </summary>
Vegetable,
/// <summary>
/// 乳製品
/// </summary>
Dairy,
/// <summary>
/// スナック
/// </summary>
Snacks
}
〇 出力
【Category : Fruit 】
Id: 1, Name: Apple, Category: Fruit, Price: 120, Quantity: 50
Id: 2, Name: Banana, Category: Fruit, Price: 80, Quantity: 30
Id: 9, Name: Grapes, Category: Fruit, Price: 200, Quantity: 15
Id: 11, Name: Orange, Category: Fruit, Price: 150, Quantity: 35
Id: 16, Name: Strawberry, Category: Fruit, Price: 300, Quantity: 20
Id: 20, Name: Peach, Category: Fruit, Price: 200, Quantity: 30
Id: 22, Name: Mango, Category: Fruit, Price: 250, Quantity: 15
Id: 26, Name: Pineapple, Category: Fruit, Price: 300, Quantity: 10
Id: 30, Name: Melon, Category: Fruit, Price: 180, Quantity: 20
【Category : Vegetable 】
Id: 3, Name: Carrot, Category: Vegetable, Price: 100, Quantity: 20
Id: 4, Name: Tomato, Category: Vegetable, Price: 120, Quantity: 40
Id: 10, Name: Potato, Category: Vegetable, Price: 50, Quantity: 100
Id: 15, Name: Cucumber, Category: Vegetable, Price: 150, Quantity: 25
Id: 17, Name: Lettuce, Category: Vegetable, Price: 90, Quantity: 30
Id: 21, Name: Radish, Category: Vegetable, Price: 70, Quantity: 20
Id: 23, Name: Sweet Corn, Category: Vegetable, Price: 110, Quantity: 40
Id: 27, Name: Spinach, Category: Vegetable, Price: 80, Quantity: 35
【Category : Dairy 】
Id: 5, Name: Milk, Category: Dairy, Price: 180, Quantity: 20
Id: 6, Name: Cheese, Category: Dairy, Price: 300, Quantity: 10
Id: 12, Name: Yogurt, Category: Dairy, Price: 150, Quantity: 20
Id: 13, Name: Ice Cream, Category: Dairy, Price: 300, Quantity: 10
Id: 18, Name: Butter, Category: Dairy, Price: 250, Quantity: 5
Id: 24, Name: Cream, Category: Dairy, Price: 220, Quantity: 10
Id: 28, Name: Whipped Cream, Category: Dairy, Price: 240, Quantity: 10
【Category : Snacks 】
Id: 7, Name: Chips, Category: Snacks, Price: 100, Quantity: 40
Id: 8, Name: Chocolate, Category: Snacks, Price: 250, Quantity: 25
Id: 14, Name: Breadsticks, Category: Snacks, Price: 120, Quantity: 50
Id: 19, Name: Crackers, Category: Snacks, Price: 100, Quantity: 40
Id: 25, Name: Biscuits, Category: Snacks, Price: 130, Quantity: 25
Id: 29, Name: Popcorn, Category: Snacks, Price: 90, Quantity: 50
コメント