LINQクエリ演算子一覧
クエリ構文で使用する演算子
以下にクエリ構文で使用できる演算子を示します。
クエリ構文の基本的な事柄についてはLINQのクエリ構文を参照してください。
「共用キーワード」は基本となる演算子とセットで使用するキーワードです。
太字の共用キーワードは必ず使用し、それ以外は任意で使用します。
演算子 | 役割 | 共用キーワード |
---|---|---|
from | シーケンスから要素を取り出し範囲変数に格納する | in |
where | Whereメソッドに相当 | |
select | Selectメソッドに相当 | into |
group | GroupByメソッドに相当 | by into |
orderby | OrderByメソッド OrderByDescendingメソッド ThenByメソッド ThenByDescendingメソッドに相当 |
ascending descending |
join | Joinメソッド GroupJoinメソッドに相当 |
in on equals into |
into | from、group句の後に新たなクエリ式を接続する join句でGroupJoinメソッドを使用する |
|
let | クエリ式内で範囲変数を宣言 |
from句
クエリ式は必ずfrom句から始まります。
from句はシーケンスから要素をひとつ取り出し、範囲変数に格納します。
IEnumerable<int> query =
from n in nums
where n % 2 == 0
select n;
複数のfrom句
from句は連続して記述することもできます。
この場合、SelectMany
メソッドの動作となります。
最初のfrom句で配列などのコレクションやクラス(構造体)が取り出される場合、次のfrom句でそれらから要素やクラスのメンバを取り出すことができます。
List<List<string>> strs = new List<List<string>>()
{
new List<string>()
{
"a", "bb", "ccc"
},
new List<string>()
{
"d", "ee"
}
};
//文字数が1より多い文字列を取り出し
IEnumerable<string> query =
from strs in lstStrs
from s in strs
where s.Length > 1
select s;
//以下のメソッド構文と同じ
IEnumerable<string> method =
lstStrs.SelectMany(strs => strs)
.Where(s => s.Length > 1)
.Select(s => s);
foreach (var x in query)
Console.Write("{0} ", x);
Console.WriteLine();
foreach (var x in method)
Console.Write("{0} ", x);
bb ccc ee bb ccc ee
最初のfrom句では、List<List<string>>
型の値からList<string>
型の範囲変数を取り出しています。
そこから次のfrom句でtring型の変数を取り出しています。
別のシーケンスをひとつのクエリ式内で同時に使用できます。
(これもSelectMany
メソッドと同様です)
List<int> nums = new List<int>()
{
1, 2
};
List<string> strs = new List<string>()
{
"aaa", "bbb", "ccc"
};
//numsとstrsを合体させて
//匿名型で返す
var query =
from n in nums
from s in strs
select new { N = n, S = s};
//以下のメソッド構文と同じ
var method =
nums.SelectMany(
_ => strs,
(n, s) => new { N = n, S = s });
foreach (var x in query)
Console.WriteLine("{0} {1} ", x.N, x.S);
1 aaa 1 bbb 1 ccc 2 aaa 2 bbb 2 ccc
where句
where句はメソッド構文のWhere
メソッドに該当します。
where句は条件に合うデータを返します。
条件で絞り込む、とも言えます。
List<int> nums = new List<int>()
{
1, 2, 5, 9, 11, 14, 18, 21
};
//偶数のみを取得
IEnumerable<int> query =
from n in nums
where n % 2 == 0
select n;
foreach (var n in query)
Console.WriteLine("{0}", n);
2 14 18
select句
select句はメソッド構文のSelect
メソッドに該当します。
select句はデータを加工し最終的な出力を行います。
List<int> nums = new List<int>()
{
2, 4, 6, 8
};
//要素を二倍にする
IEnumerable<int> query =
from n in nums
select n * 2;
foreach (var n in query)
Console.Write("{0} ", n);
4 8 12 16
into演算子
select句が出現するとクエリ式は終了します。
select句の後ろに別のクエリ式を続けたい場合はinto
演算子を使用します。
List<int> nums = new List<int>()
{
2, 4, 6, 8
};
//最初のselect句で要素を二倍に
//次のwhere句で値が10以上の要素を取り出し
IEnumerable<int> query =
from n1 in nums
select n1 * 2 into n2
where n2 > 10
select n2;
foreach (var n in query)
Console.Write("{0} ", n);
12 16
into
演算子に続く範囲変数n2
は、直前のselect句で加工された結果の値が格納されています。
これはつまり以下のメソッド構文と同じになります。
(メソッド構文の場合は最後のSelect
メソッドは不要)
IEnumerable<int> query =
nums.Select(n1 => n1 * 2)
.Where(n2 => n2 > 10)
.Select(n2 => n2);
なお、into
演算子の前と後とでは別のクエリ式なので、範囲変数はそれぞれで独立しています。
上のコードの範囲変数n1
はinto
演算子の後では使えません。
分かりやすくするために別名にしていますが、into
演算子の前後で同じ名前の範囲変数があっても問題ありません。
group句
group句はメソッド構文のGroupBy
メソッドに該当します。
group句は任意のキーでデータをグループ化します。
class NumStr
{
public int Num;
public string Str;
public NumStr(int n, string s)
{
Num = n;
Str = s;
}
}
static void Main(string[] args)
{
List<NumStr> lstNS = new List<NumStr>()
{
new NumStr(1, "aaa"),
new NumStr(2, "bbb"),
new NumStr(3, "ccc"),
new NumStr(1, "ddd"),
new NumStr(3, "eee"),
};
IEnumerable<IGrouping<int, NumStr>> query =
from t in lstNS
group t by t.Num;
//以下のメソッド構文と同じ
IEnumerable<IGrouping<int, NumStr>> method =
lstNS.GroupBy(ns => ns.Num);
foreach (IGrouping<int, NumStr> g in query)
{
foreach (NumStr ns in g)
Console.Write("{0}-{1} ", ns.Num, ns.Str);
Console.WriteLine();
}
Console.ReadLine();
}
1-aaa 1-ddd 2-bbb 3-ccc 3-eee
文法はgroup グループ化される要素 by キー
の順序となります。
group句が出現するとクエリ式は終了します。
group句の後ろに別のクエリ式を接続するにはinto演算子を使用します。
orderby句
orderby句はメソッド構文のOrderby
、OrderByDescending
メソッドに該当します。
orderby句はシーケンスを並べ替えます。
List<int> nums = new List<int>()
{
3, 5, 14, 11, 2, 19
};
//昇順
IEnumerable<int> query1 =
from n in nums
orderby n //ascendingは不要
select n;
//降順
IEnumerable<int> query2 =
from n in nums
orderby n descending
select n;
foreach (var n in query1)
Console.Write("{0} ", n);
Console.WriteLine();
foreach (var n in query2)
Console.Write("{0} ", n);
2 3 5 11 14 19 19 14 11 5 3 2
orderby句の並べ替えはデフォルトで昇順なので、ascending
演算子は付ける必要はありません。
(付けても構いません)
ascending
、descending
演算子に続いてコンマ(,
)を書き、さらに要素を指定すると、ThenBy
、ThenByDescending
メソッドの動作となります。
これらは並べ替え順序が同じ要素同士を別の条件で並べ替えをします。
class NumStr
{
public int Num;
public string Str;
public NumStr(int n, string s)
{
Num = n;
Str = s;
}
}
static void Main(string[] args)
{
List<NumStr> lstNS = new List<NumStr>()
{
new NumStr(5, "aaa"),
new NumStr(8, "bbb"),
new NumStr(2, "ccc"),
new NumStr(2, "ddd"),
new NumStr(8, "eee")
};
//昇順→昇順
IEnumerable<NumStr> query1 =
from ns in lstNS
orderby ns.Num, ns.Str
select ns;
//昇順→降順
IEnumerable<NumStr> query2 =
from ns in lstNS
orderby ns.Num, ns.Str descending
select ns;
foreach (NumStr ns in query1)
Console.WriteLine("{0} {1}", ns.Num, ns.Str);
Console.WriteLine();
foreach (NumStr ns in query2)
Console.WriteLine("{0} {1}", ns.Num, ns.Str);
Console.ReadLine();
}
2 ccc 2 ddd 5 aaa 8 bbb 8 eee 2 ddd 2 ccc 5 aaa 8 eee 8 ddd
join句
join句はメソッド構文のJoin
メソッドに該当します。
join句は二つのシーケンスで共通する要素をキーとして結合し、新しいシーケンスを作ります。
//役職
class Position
{
public int ID;
public string Name;
public Position(int id, string name)
{
ID = id;
Name = name;
}
}
//人物
class Person
{
public int ID;
public string Name;
public int PositionID;
public Person(int id, string name, int positionID)
{
ID = id;
Name = name;
PositionID = positionID;
}
}
static void Main(string[] args)
{
List<Position> positions = new List<Position>()
{
new Position(1, "部長"),
new Position(2, "課長"),
new Position(3, "係長"),
new Position(4, "ヒラ"),
};
List<Person> persons = new List<Person>()
{
new Person(1, "A山B太", 1),
new Person(2, "C谷D男", 2),
new Person(3, "E下F子", 2),
new Person(4, "G田H雄", 3),
new Person(5, "I森J美", 3),
new Person(6, "K川L子", 4),
new Person(7, "M沢N助", 4),
new Person(8, "O木P一", 4),
};
//匿名型なのでvar
var query =
from pos in positions
join per in persons on pos.ID equals per.PositionID
select new { PositionName = pos.Name, Name = per.Name };
foreach (var x in query)
Console.WriteLine("{0} {1}", x.PositionName, x.Name);
Console.ReadLine();
}
部長 A山B太 課長 C谷D男 課長 E下F子 係長 G田H雄 係長 I森J美 ヒラ K川L子 ヒラ M沢N助 ヒラ O木P一
in
キーワードで要素を範囲変数に取り出します。
次のon
キーワードで連結するキーの指定を行います。
キー同士はequals
キーワードで連結します。
上記の例ではPosition
クラスのID
フィールドとPerson
クラスのPositionID
フィールドを共通のキーとして、新しい匿名型(の集合であるIEnamerable型)を作りだしてます。
join句はinto
演算子と共に使用するとGroupJoin
メソッドの動作となります。
var query =
from pos in positions
join per in persons on pos.ID equals per.PositionID into g
select new { PositionName = pos.Name, Groups = g };
foreach (var x in query)
{
Console.Write("{0} ", x.PositionName);
foreach (Person p in x.Groups)
Console.Write("{0} ", p.Name);
Console.WriteLine();
}
部長 A山B太 課長 C谷D男 E下F子 係長 G田H雄 I森J美 ヒラ K川L子 M沢N助 O木P一
g
にはキーで共通化されたグループ(シーケンス)が格納されます。
let句
let句はクエリ式内で新しい範囲変数の使用を宣言します。
これはクエリ式内で必要な計算等の結果を保存しておくことができます。
List<string> strs = new List<string>()
{
"This is a sample code of CSharp.",
"This is a pen.",
"I am a student boy."
};
//単語数が5つ以上
//かつ「is」が含まれる文を取得
IEnumerable<string> query =
from str in strs
let words = str.ToLower().Split(' ')
where words.Length >= 5 && words.Contains("is")
select str;
foreach (var x in query)
Console.WriteLine("{0} ", x);
This is a sample code of CSharp.