連載:[完全版]究極のC#プログラミング

Chapter15 LINQとクエリ式

川俣 晶
2010/03/17
Page 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

15.15 複数ソースを関連付けるjoin句

 複数のソースの値を関連付けることは、複数のfrom句を使うことでも実現できる。たとえば、次のリスト15.17のようなクエリ式を書くことで、同じId番号を持つ商品情報オブジェクトと商品販売価格オブジェクトを関連付けることができ、名前と価格を組み合わせたリストを出力することができる。

using System;
using System.Linq;

class Program
{
  class 商品情報
  {
    public int Id;
    public string 名前;
  }

  class 商品販売価格
  {
    public int Id;
    public int 価格;
  }

  static void Main(string[] args)
  {
    商品情報[] 商品情報データ =
    {
      new 商品情報() { Id = 1, 名前="PC-8001" },
      new 商品情報() { Id = 2, 名前="MZ-80K" },
      new 商品情報() { Id = 3, 名前="Basic Master Level-3" },
    };

    商品販売価格[] 商品販売価格データ =
    {
      new 商品販売価格() { Id = 1, 価格 = 148000 },
      new 商品販売価格() { Id = 2, 価格 = 178000 },
      new 商品販売価格() { Id = 3, 価格 = 229000 },
    };

    var query = from x in 商品情報データ
                from y in 商品販売価格データ
                where x.Id == y.Id
                select new { Name = x.名前, Price = y.価格 };

    foreach (var 商品 in query) {
      Console.WriteLine("{0} {1:C}", 商品.Name, 商品.Price);
    }
    // 出力:
    // PC-8001 \148,000
    // MZ-80K \178,000
    // Basic Master Level-3 \229,000
  }
}
リスト15.17 複数のソースを関連付ける

 しかし、このようなコードは効率が良くない。本章で紹介した掛け算の九九表サンプルを見てわかるとおり、2つのソースについてすべて総当たりで調べることになるためだ。つまり、商品情報が3つ、商品販売価格が3つなら、3×3=9回の判定が実行される。

 これを改善するには、関連付けという役割に特化したjoin句を使用するとよい。具体的には、クエリ式を次のリスト15.18のように書き直す。

var query = from x in 商品情報データ
            join y in 商品販売価格データ on x.Id equals y.Id
            select new { Name = x.名前, Price = y.価格 };
リスト15.18 join句への書き換え

 これは、join句の使い方の1つである「内部結合」を使用したものである。この場合、join句は、次のような書式で記述する。

join [型名、省略可] 識別子 in 式1 on 式2 equals 式3
join句の構文

 ここで「join …… in ……」の部分は、「from …… in ……」の構文と似ている。しかし、決定的に違うのは「on」以降の構文が存在する点である。これは、2つのソースを関連付ける条件を指定するために存在する。

 ここで注意すべき点は、from句の場合、関連付けるソースを選ぶ条件として「where x.Id == y.Id」と記述したが、join句では「on x.Id equals y.Id」と記述していることである。より具体的にいえば、「==」という汎用の演算子を使っているか、「equals」というjoin句専用キーワードを使っているかの相違である。つまり、where句で条件を指定する場合は、あらゆる式を自由に記述できたが、join句では「等価」という判定しか行うことができない。

 この制約は、逆にいえば、join句を使用するには「等価」と判定できる値を2つのソースが含んでいなければならないことも示す。


 INDEX
  [完全版]究極のC#プログラミング
  Chapter15 LINQとクエリ式
    1.15.1 LINQの面白さ
    2.15.2 LINQとは何か?
    3.15.3 「値の集まり」に対する演算
    4.15.4 なぜLINQなのか?
    5.15.5 最も基本的なLINQ
    6.15.6 LINQの本質は列挙
    7.15.7 LINQを使ううえでの注意点
    8.15.8 クエリ結果を加工する
    9.15.9 複数のソースからクエリする
    10.15.10 条件で絞り込む
    11.15.11 一部項目のみselectする
    12.15.12 シンプルなソート
    13.15.13 クエリの接続
    14.15.14 クエリ結果のグループ化
  15.15.15 複数ソースを関連付けるjoin句
    16.15.16 from句とjoin句のパフォーマンス
    17.15.17 join句のグループ化結合
    18.15.18 join句の左外部結合
    19.15.19 単独で使うDefaultIfEmptyメソッド
    20.15.20 内部列挙を伴うfrom句の二重使用
    21.15.21 let句
    22.15.22 クエリのインスタンス化
    23.15.23 クエリ結果の個数を得る
    24.15.24 Anyメソッドと存在チェック/【C#olumn】クエリ式のデバッグテクニック
    25.15.25 まとめ/【C#olumn】LINQの難しさ/【Exercise】練習問題
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間