LINQの基礎(2)

引き続き、LINQの基礎的なメソッドについてまとめる

メソッド名 機能 返すデータ型
OrderBy 並べ替え シーケンス
Take 先頭から指定個数の要素をシーケンスとして取得 シーケンス
Skip 指定個数スキップ後のシーケンスを取得 シーケンス
TakeWhile 先頭から連続する条件を満たすシーケンスを取得 シーケンス
SkipWhile 条件を満たす要素をスキップし、残りのシーケンスを取得 シーケンス
Concat 2つのシーケンスを連結 シーケンス
First 最初の要素を取得 要素の型
Last 最後の要素を取得 要素の型
SequenceEqual 2つのシーケンスが順序を含めて等しいか判定 bool
All すべての要素が条件を満たすか判定 bool
Any 条件を満たす要素があるか判定 bool
Contains 指定の要素が含まれているか判定 bool

OrderBy

配列の要素を昇順(小さい順)に並べ替える。

int[] a = { 3, 1, 4 };
Console.WriteLine(string.Join(",",a.OrderBy(n=>n)));
実行結果. 1,3,4

ラムダ式 n => n は a の要素を「そのまま」昇順にソートすることを指定したことになる。 ラムダ式の部分を「 n => -n 」に変更すると、 配列 a の要素を (-1) 倍したものを昇順にソートした結果が a に反映され、 結果 a の要素を降順にソートすることになる。

降順のソート.

int[] a = { 3, 1, 4 };
Console.WriteLine(string.Join(",",a.OrderBy(n=>-n)));
実行結果. 4,3,1

Take

シーケンスの先頭から指定した個数の要素を取り出す。 注:例え一つのデータだけ抜き出しても、シーケンスとみなされる。

int[] a = { 3, 1, 4, 1, 5, 9 };
Console.WriteLine(string.Join(",",a.Take(3)));
実行結果. 3,1,4

Skip

指定した個数だけ要素をスキップして、残ったシーケンスを取得する。

int[] a = { 3, 1, 4, 1, 5, 9 };
Console.WriteLine(string.Join(",",a.Skip(3)));
実行結果. 1,5,9

TakeWhile

シーケンスの先頭から、連続する指定した条件を満たす要素をシーケンスとして取得する。

int[] a = { 3, 1, 4, 1, 5, 9 };
Console.WriteLine(string.Join(",", a.TakeWhile(n => n <= 3)));
実行結果. 3,1

SkipWhile

シーケンスの先頭から、指定した条件を満たす要素をスキップして、残りのシーケンスを取得する。

int[] a = { 3, 1, 4, 1, 5, 9 };
Console.WriteLine(string.Join(",", a.SkipWhile(n => n <= 4)));
実行結果. 5,9

Concat

二つのシーケンスをならべて、新たなシーケンスを得る。

int[] a = { 3, 1 };
int[] b = { 4, 1, 5 };
Console.WriteLine(string.Join(",",a.Concat(b)));
実行結果. 3,1,4,1,5

First

最初の要素を取得する。Take(1)と同じように思えるが、Take(1)はあくまで、シーケンスであることに注意する。 一方、Firstメソッドで得られるものは要素そのもの。

int[] a = { 1, 2, 3 };
Console.WriteLine(a.First());
Console.WriteLine(a.Take(1));
実行結果. 1
System.Linq.Enumerable以下略

ここで、実行結果2行目の表示がおかしくなるのは、Take(1)が配列の要素であるint型ではなく、 int型の要素からならシーケンスとみなされるためである。

SequenceEqual

2つのシーケンスが等しいかどうかは、「==」では判定できない。 実際、次のコードでは、等しいはずのシーケンスが異なるものだと判定されてしまう。

int[] a = { 1, 2, 3 };
int[] b = { 1, 2, 3 };
Console.WriteLine(a == b);
実行結果. False

SequenceEqualを用いると正しく判定される。

int[] a = { 1, 2, 3 };
int[] b = { 1, 2, 3 };
Console.WriteLine(a.SequenceEqual(b));
実行結果. True

All

全ての要素が条件をみたすかを判定する。

string[] words = { "april", "march", "may" };
Console.WriteLine(words.All(x => x.Contains("a")));
実行結果. True

全ての要素に "a" という文字が含まれているからTureになる。

Any

条件を満たす要素があるかどうか判定する。

string[] words = { "0", "101", "011", "1","01" };
Console.WriteLine(words.Any(x => x.Contains("11")));
実行結果. True

一つでも "11" を含む文字列があれば True となる。今の場合3番目の要素である"011"が条件を満たす。

Contains

指定した要素が含まれているかどうかを判定。

string[] words = { "0", "101", "011", "1","01" };
Console.WriteLine(words.Contains("101"));
実行結果. True

注:Contains は同名のメソッドが string クラスにもあるが、今使用したのは LINQ のメソッド。