基礎から学ぶC#入門 90日コース | 実践的なC#プログラミング - Day 59:LINQ実践

C# 90日で身につけるC#
スポンサーリンク
スポンサーリンク

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 実践の楽しさを、自分のコードで味わっていっていただければうれしいです。

タイトルとURLをコピーしました