LINQ で 複数のfromがある構文について - C#

LINQ で 複数のfromがある構文について紹介します。

概要

LINQで参照するオブジェクト内にさらにList型などのシーケンス型が含まれる場合、from文を複数記述した「複合from句」を利用できます。また、複数のデータソースを結合して利用する場合にも複数のform句を利用します。

プログラム : 複合from句

UI

下図のUIを作成します。Buttonと複数行のTextBoxを配置します。

コード

下記のコードを記述します。
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;

namespace MultiFromLinq
{
  public partial class FormMain : Form
  {
    public class MyItem
    {
      public string name;
      public List<int> score;

      public MyItem(string namev, int[] scorev)
      {
        name = namev;
        score = new List<int>(scorev);
       }
    }

    public FormMain()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      List<MyItem> mlist = new List<MyItem>();

      mlist.Add(new MyItem("ぺんた", new int[] { 85 ,90, 86}));
      mlist.Add(new MyItem("あでり", new int[] { 45, 60, 55 }));
      mlist.Add(new MyItem("じぇんつ", new int[] { 58, 70, 32 }));
      mlist.Add(new MyItem("いわとび", new int[] { 42, 55, 95 }));
      mlist.Add(new MyItem("ぐれい", new int[] { 65, 64, 71 }));
      mlist.Add(new MyItem("こうてい", new int[] { 95, 88, 86 }));

      var query = from item in mlist
                  from sc in item.score
                  where sc > 70
                  select new { name = item.name, sc };

      foreach (var i in query) {
        textBox1.Text += string.Format("{0} - {1:d}\r\n", i.name, i.sc);
      }
    }
  }
}

解説

下記のコードで情報を管理するクラスを定義します。今回のクラスはメンバ変数にstring型のnameプロパティと、int型のListのscore変数を宣言します。また、コンストラクタも作成し、コンストラクタに与えられた引数の値でメンバ変数の値を初期化する動作とします。
    public class MyItem
    {
      public string name;
      public List<int> score;

      public MyItem(string namev, int[] scorev)
      {
        name = namev;
        score = new List<int>(scorev);
       }
    }

データの準備をするコードです。MyItem型のリストを作成します。作成後、リストに要素を6つ追加します。
      List<MyItem> mlist = new List<MyItem>();

      mlist.Add(new MyItem("ぺんた", new int[] { 85 ,90, 86}));
      mlist.Add(new MyItem("あでり", new int[] { 45, 60, 55 }));
      mlist.Add(new MyItem("じぇんつ", new int[] { 58, 70, 32 }));
      mlist.Add(new MyItem("いわとび", new int[] { 42, 55, 95 }));
      mlist.Add(new MyItem("ぐれい", new int[] { 65, 64, 71 }));
      mlist.Add(new MyItem("こうてい", new int[] { 95, 88, 86 }));

LINQでリストを検索します。下記のコードでは、MyItemのscoreが70以上の項目があれば、その要素のnameとscoreをオブジェクトをで返す動作になります。
      var query = from item in mlist
                  from sc in item.score
                  where sc > 70
                  select new { name = item.name, sc };

LINQの結果をテキストボックスに表示します。
      foreach (var i in query) {
        textBox1.Text += string.Format("{0} - {1:d}\r\n", i.name, i.sc);
      }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。用意したデータの中で、scoreが70以上のscoreとその要素のnameの組の一覧が表示されます。

プログラム : 結合する場合

LINQで結合する場合のコードを紹介します。

UI

下図のUIを作成します。フォームにButtonと複数行のTextBoxを配置します。

コード

下記のコードを記述します。
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;

namespace MultiFromLinq
{
  public partial class FormJoinMultiFrom : Form
  {
    public List<int> List1;
    public List<string> List2;
    
    public FormJoinMultiFrom()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      List1 = new List<int>(new int[] { 1, 2, 3});
      List2 = new List<string>(new string[] { "adelie", "gentoo", "gray" });

      var joinQuery =
            from flag in List1
            from name in List2
            select new { flag, name };

      foreach(var i in joinQuery){
        textBox1.Text += string.Format("{0} - {1:d}\r\n", i.flag, i.name);
      }
    }
  }
}

解説

int型のリストと、string型のリストを作成し、初期値を設定します。
      List1 = new List<int>(new int[] { 1, 2, 3});
      List2 = new List<string>(new string[] { "adelie", "gentoo", "gray" });

LINQを利用してリストにアクセスしてデータを取得します。List1とList2のそれぞれの値を取得し、取得した値をオブジェクトにして返します。それぞれのリストの値に対してアクセスするため、すべての組み合わせである9つのオブジェクトを返します。
      var joinQuery =
            from flag in List1
            from name in List2
            select new { flag, name };

LINQで生成されるオブジェクト
flagname
1adelie
1gentoo
1gray
2adelie
2gentoo
2gray
3adelie
3gentoo
3gray

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。flagとnameの組み合わせの値がテキストボックスに表示されます。それぞれのリストのすべての値の組み合わせが表示されていることが確認できます。

プログラム : 結合する場合(whereを利用)

whereを利用して条件を加えた結合の例を紹介します。

UI

下図のUIを作成します。フォームにButtonと複数行のTextBoxを配置します。今回は[button2]のみを利用します。

コード

下記のコードを記述します。
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;

namespace MultiFromLinq
{
  public partial class FormJoinMultiFrom : Form
  {
    public List<int> List1;
    public List<string> List2;
    
    public FormJoinMultiFrom()
    {
      InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {
      List1 = new List<int>(new int[] { 1, 2, 3 });
      List2 = new List<string>(new string[] { "adelie", "gentoo", "gray" });

      var joinQuery =
            from flag in List1
            where flag !=2
            from name in List2
            where name != "gray"
            select new { flag, name };

      foreach (var i in joinQuery) {
        textBox1.Text += string.Format("{0} - {1:d}\r\n", i.flag, i.name);
      }
    }
  }
}

解説

先の結合例と同様のコードですがLINQ部分のコードが異なります。LINQにwerer節が追加され、List1の値が2以外、List2の値が"gray"以外の要素に対してそれぞれの組み合わせの値のオブジェクトを返します。
      var joinQuery =
            from flag in List1
            where flag !=2
            from name in List2
            where name != "gray"
            select new { flag, name };

LINQで生成されるオブジェクト
flagname
1adelie
1gentoo
3adelie
3gentoo

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button2]をクリックします。List1の値が2以外、List2の値が"gray"以外の要素に対してそれぞれの組み合わせの値がテキストボックスに表示されます。


著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2024-01-07
作成日: 2018-01-05
iPentec all rights reserverd.