Day 59 のゴールと全体像
Day 59 では、これまで学んできた LINQ を「実践」で使ってみることをテーマにします。 題材は、とてもイメージしやすい 商品検索システム です。
扱う機能は次の5つです。
- 商品名検索
- カテゴリ検索
- 価格検索
- 並び替え
- 集計
「LINQって便利そうだけど、実際のシステムでどう使うの?」 というモヤっとした疑問を、今日でかなりスッキリさせていきます。
サンプルコードをベースに、少しずつ機能を足していく形で進めますので、 肩の力を抜いて読み進めていただければうれしいです。
商品検索システムの土台を作る
まずは、検索対象となる「商品」を表すクラスと、 サンプルデータを用意しておきます。
Product クラスの定義
using System;
class Product
{
// 商品ID(識別用)
public int Id { get; set; }
// 商品名
public string Name { get; set; }
// カテゴリ(例:食品、文房具など)
public string Category { get; set; }
// 価格
public int Price { get; set; }
}
C#とてもシンプルですが、
- 「何の商品か」 → Name
- 「どんなカテゴリか」 → Category
- 「いくらか」 → Price
という、検索に必要な情報はひと通り揃っています。
サンプルデータを用意する
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// 商品一覧(サンプルデータ)
var products = new List<Product>
{
new Product { Id = 1, Name = "りんご", Category = "食品", Price = 120 },
new Product { Id = 2, Name = "バナナ", Category = "食品", Price = 150 },
new Product { Id = 3, Name = "ノート", Category = "文房具", Price = 200 },
new Product { Id = 4, Name = "鉛筆", Category = "文房具", Price = 80 },
new Product { Id = 5, Name = "消しゴム", Category = "文房具", Price = 100 },
new Product { Id = 6, Name = "パン", Category = "食品", Price = 180 }
};
// ここから LINQ を使った検索・並び替え・集計を行っていきます。
}
}
C#この products リストを相手に、 LINQ を使っていろいろな検索をしていく、という流れになります。
商品名検索 ― 部分一致で探す
まずは「商品名で検索する」機能から見ていきます。 よくあるのは「入力したキーワードを含む商品を探す」というパターンです。
Contains を使った部分一致検索
// 「ノート」という文字を含む商品を検索する
var keyword = "ノート";
// Name に keyword が含まれているかどうかで絞り込み
var nameResult = products
.Where(p => p.Name.Contains(keyword)); // 部分一致検索
Console.WriteLine($"商品名に「{keyword}」を含む商品:");
foreach (var p in nameResult)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, カテゴリ: {p.Category}, 価格: {p.Price}円");
}
C#ここで押さえておきたいポイント
p.Name.Contains(keyword)→ 「商品名にキーワードが含まれているか」を判定しています。Whereと組み合わせることで、 「条件に合う商品だけ」を簡単に取り出せます。
実際の検索画面でも、 「キーワードで検索」という機能は定番ですので、 この書き方はぜひ覚えておきたいところです。
カテゴリ検索 ― 特定カテゴリだけを絞り込む
次に、「カテゴリで絞り込む」検索を見ていきます。 たとえば「食品だけ見たい」「文房具だけ見たい」といった場面です。
カテゴリを指定して検索する
// 「食品」カテゴリの商品だけを検索する
var category = "食品";
var categoryResult = products
.Where(p => p.Category == category); // カテゴリが一致するものだけ
Console.WriteLine($"カテゴリ「{category}」の商品:");
foreach (var p in categoryResult)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, 価格: {p.Price}円");
}
C#ポイント
p.Category == categoryという条件で、 「カテゴリが完全一致する商品だけ」を絞り込んでいます。- カテゴリは「選択式(プルダウンなど)」になることが多いので、 完全一致で比較することが多いです。
価格検索 ― 範囲指定で探す
次は「価格で検索する」機能です。 たとえば「100円以上200円以下の商品だけ見たい」といった、 範囲指定の検索がよく使われます。
価格の範囲で絞り込む
// 100円以上200円以下の商品を検索する
int minPrice = 100;
int maxPrice = 200;
var priceResult = products
.Where(p => p.Price >= minPrice && p.Price <= maxPrice);
Console.WriteLine($"{minPrice}円以上 {maxPrice}円以下の商品:");
foreach (var p in priceResult)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, 価格: {p.Price}円");
}
C#ポイント
p.Price >= minPrice && p.Price <= maxPrice→ 「下限以上かつ上限以下」という条件で範囲指定しています。- 価格検索は、ユーザーが「予算感」をもとに商品を探すときに、 とてもよく使われる機能です。
並び替え ― 価格順・名前順で並べる
検索結果を表示するときに、 「並び順」を変えられると、ぐっと使いやすくなります。
ここでは、
- 価格の昇順(安い順)
- 価格の降順(高い順)
- 名前の昇順(辞書順)
の3パターンを見ていきます。
価格の昇順(安い順)
// 価格の安い順に並び替える
var orderedByPriceAsc = products
.OrderBy(p => p.Price); // Price を基準に昇順
Console.WriteLine("価格の安い順:");
foreach (var p in orderedByPriceAsc)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, 価格: {p.Price}円");
}
C#価格の降順(高い順)
// 価格の高い順に並び替える
var orderedByPriceDesc = products
.OrderByDescending(p => p.Price); // Price を基準に降順
Console.WriteLine("価格の高い順:");
foreach (var p in orderedByPriceDesc)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, 価格: {p.Price}円");
}
C#名前の昇順(辞書順)
// 名前の辞書順に並び替える
var orderedByName = products
.OrderBy(p => p.Name); // Name を基準に昇順
Console.WriteLine("名前の昇順:");
foreach (var p in orderedByName)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, 価格: {p.Price}円");
}
C#並び替えのポイント
OrderBy/OrderByDescendingは「並び替えの基準」を指定するメソッドです。- 基準には、数値でも文字列でも、オブジェクトのプロパティでも指定できます。
- 検索結果に対してさらに並び替えをかける、という使い方もよくあります。
集計 ― 件数・合計・カテゴリ別集計
最後に、「集計」を使って商品一覧を数字の視点から眺めてみます。
ここでは、
- 全商品の件数
- 全商品の合計金額
- カテゴリごとの件数と合計金額
を求めてみます。
全商品の件数と合計金額
// 全商品の件数
int totalCount = products.Count();
// 全商品の合計金額(価格の合計)
int totalPrice = products.Sum(p => p.Price);
Console.WriteLine($"商品数: {totalCount} 件");
Console.WriteLine($"価格の合計: {totalPrice} 円");
C#カテゴリごとの件数と合計金額
// カテゴリごとにグループ分け
var categoryGroups = products.GroupBy(p => p.Category);
Console.WriteLine("カテゴリごとの集計:");
foreach (var group in categoryGroups)
{
string category = group.Key;
// そのカテゴリに属する商品の件数
int count = group.Count();
// そのカテゴリに属する商品の価格合計
int sumPrice = group.Sum(p => p.Price);
Console.WriteLine($"カテゴリ: {category}, 件数: {count} 件, 合計: {sumPrice} 円");
}
C#集計のポイント
Count/Sumは、全体だけでなく「グループごと」にも使えます。GroupByと組み合わせることで、 「カテゴリ別」「店舗別」「ユーザー別」などの集計が簡単に書けます。
まとめて動かす「商品検索システム」テンプレート
ここまでの内容をひとつにまとめた、 「LINQ 実践・商品検索システム」のミニテンプレートを紹介します。
using System;
using System.Collections.Generic;
using System.Linq;
class Product
{
public int Id { get; set; } // 商品ID
public string Name { get; set; } // 商品名
public string Category { get; set; } // カテゴリ
public int Price { get; set; } // 価格
}
class Program
{
static void Main()
{
var products = new List<Product>
{
new Product { Id = 1, Name = "りんご", Category = "食品", Price = 120 },
new Product { Id = 2, Name = "バナナ", Category = "食品", Price = 150 },
new Product { Id = 3, Name = "ノート", Category = "文房具", Price = 200 },
new Product { Id = 4, Name = "鉛筆", Category = "文房具", Price = 80 },
new Product { Id = 5, Name = "消しゴム", Category = "文房具", Price = 100 },
new Product { Id = 6, Name = "パン", Category = "食品", Price = 180 }
};
// 1. 商品名検索
var keyword = "ノート";
var nameResult = products.Where(p => p.Name.Contains(keyword));
Console.WriteLine($"【商品名検索】「{keyword}」を含む商品:");
foreach (var p in nameResult)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, カテゴリ: {p.Category}, 価格: {p.Price}円");
}
Console.WriteLine();
// 2. カテゴリ検索
var category = "食品";
var categoryResult = products.Where(p => p.Category == category);
Console.WriteLine($"【カテゴリ検索】カテゴリ「{category}」の商品:");
foreach (var p in categoryResult)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, 価格: {p.Price}円");
}
Console.WriteLine();
// 3. 価格検索(範囲指定)
int minPrice = 100;
int maxPrice = 180;
var priceResult = products.Where(p => p.Price >= minPrice && p.Price <= maxPrice);
Console.WriteLine($"【価格検索】{minPrice}円以上 {maxPrice}円以下の商品:");
foreach (var p in priceResult)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, 価格: {p.Price}円");
}
Console.WriteLine();
// 4. 並び替え(価格の安い順)
var orderedByPriceAsc = products.OrderBy(p => p.Price);
Console.WriteLine("【並び替え】価格の安い順:");
foreach (var p in orderedByPriceAsc)
{
Console.WriteLine($"ID: {p.Id}, 名前: {p.Name}, 価格: {p.Price}円");
}
Console.WriteLine();
// 5. 集計(全体とカテゴリ別)
int totalCount = products.Count();
int totalPrice = products.Sum(p => p.Price);
Console.WriteLine("【集計】全体:");
Console.WriteLine($"商品数: {totalCount} 件");
Console.WriteLine($"価格の合計: {totalPrice} 円");
Console.WriteLine();
var categoryGroups = products.GroupBy(p => p.Category);
Console.WriteLine("【集計】カテゴリごと:");
foreach (var group in categoryGroups)
{
string cat = group.Key;
int count = group.Count();
int sumPrice = group.Sum(p => p.Price);
Console.WriteLine($"カテゴリ: {cat}, 件数: {count} 件, 合計: {sumPrice} 円");
}
}
}
C#このテンプレートをベースに、
- キーワードやカテゴリ、価格範囲を変えてみる
- 並び替えの基準を変えてみる(名前順・カテゴリ順など)
- 集計内容を増やしてみる(平均価格、最大・最小価格など)
といった小さな工夫を重ねていくことで、 LINQ を使った「実践的な検索・集計」の感覚が、ぐっと身近になっていきます。
Day 59 のまとめ
Day 59 では、
- 商品名検索(
Where+Contains) - カテゴリ検索(
Where+ 完全一致) - 価格検索(
Where+ 範囲指定) - 並び替え(
OrderBy/OrderByDescending) - 集計(
Count/Sum/GroupBy)
を組み合わせた 商品検索システム を通して、 LINQ の実践的な使い方を学びました。
ここまで来ると、
- 「一覧データをどう扱うか」という視点でコードを書けるようになり、
- 検索・並び替え・集計といった“よくある機能”の裏側が、 かなりクリアに見えてくるはずです。
ぜひ、
- 自分で商品データを増やしてみる
- 条件や並び替え、集計の内容を変えてみる
- コンソール入力(
Console.ReadLine())と組み合わせて、 簡易的な「対話型検索システム」に発展させてみる
といった一歩を重ねながら、 LINQ 実践の楽しさを、自分のコードで味わっていっていただければうれしいです。
