眠くて勉強内容が頭に入りません。これでは仕事ができません。el(える)です。
今回はC#3.0のバージョンから導入されたLINQ(リンク)を勉強していきます。
この辺はさっぱり頭に入ってないので、書きながら理解していきたいとおもいます。
LINQ
LINQとは(Language INtegrated Query)の略称で統合言語クエリと訳されます。
C#3.0から導入された仕組みで、
配列やコレクションに格納されているデータをとても簡単に整理できます。
配列中のデータから特定の条件を満たすデータを取り出したり、 配列中のデータ1つひとつに処理を施したり といった処理が数行で書けるようになります。LINQを使うには処理条件などを指定するためラムダ式と呼ばれる式を使います
ラムダ式から見ていきましょう。
ラムダ式
ラムダ式とは超簡単に説明すると、
「 戻り値を返す短いメソッドを、より簡潔に書く方法 」のようです。
ラムダ式の書式
(引数) => 戻り値の計算式
たとえば、引数に2を足して返すメソッドがあったとします。
int Add(int n)
{
return n + 2;
}
このメソッドと同じ働きをするラムダ式は、
n => n + 2
となります。
引数が2つの場合、
int Add(int a, int b)
{
return a + b;
}
これをラムダ式で書くと、
(a,b) => a + b
となります。
int型以外の戻り値を持つメソッド
戻り値にはどの型でも指定できます。
引数の値が0ならtrue、そうでなければfalseを返すメソッドです。
bool IsPositive(int n)
{
return n >= 0;
}
これをラムダ式で書くと、
n => n >= 0
となります。
ラムダ式を知ったうえでのLINQ
ここからは例題を通してLINQの使い方を学びましょう。
5個のHPを配列に入れます。
配列の中からHPが500以上の要素だけを抜き出すにはどうしたらいいでしょう。
LINQを使わずに書いた例です。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample { class Program { static void Main(string[] args) { int[] hp = { 420, 120, 600, 0, 1200 }; List<int> newHP = new List<int>(); for (int i = 0; i < hp.Length; i++) { if (hp[i] >= 500) { newHP.Add(hp[i]); } } foreach (int n in newHP) { Console.WriteLine(n); } } } }
これをLINQを使って書くと、
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample { class Program { static void Main(string[] args) { int[] hp = { 420, 120, 600, 0, 1200 }; var newHP = hp.Where(n => n >= 500); foreach (int h in newHP) { Console.WriteLine(h); } } } }
こうなります。
かなり簡潔にかけることがわかりました。
このプログラムはWhereメソッドを使っています。
Whereは引数に指定した ラムダ式の結果がtrueになるものだけを取り出す メソッドです。
ラムダ式の条件にあうデータだけを取り出す書式
変数名.Where(ラムダ式)
ここではWhereメソッドの引数に「n => n >= 500」というラムダ式を渡しています。
引数にnを取り、nが500以上ならtrueを返すメソッドと同じ処理です。
その結果、HPが500以上だけを取り出すことができます。
Whereメソッドによって作られたデータは、戻り値として取得できます。
戻り値の型はvar型になります。
var型とはint型やfloar型のように特定の型を表すものではなく、
代入された値によってコンパイラが自動的に型を判断してくれる型 です。
LINQのメソッドの戻り値は基本的にvar型で受け取ります。
すべてのHPを100減らす
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample { class Program { static void Main(string[] args) { int[] hp = { 420, 120, 600, 800, 1200 }; List<int> newHp = new List<int>(); for (int i = 0; i < hp.Length; i++) { newHp.Add(hp[i] - 100); } foreach (int n in newHp) { Console.WriteLine(n); } } } }
LINQを使うと、このようになります。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample { class Program { static void Main(string[] args) { int[] hp = { 420, 120, 600, 800, 1200 }; var newHp = hp.Select(n => n - 100); foreach (int n in newHp) { Console.WriteLine(n); } } } }
Selectメソッドを使っています。
配列の要素を1つずつ取り出して、引数に指定したラムダ式の処理を加えます。
配列やコレクションのデータにラムダ式の処理を加えて新しいデータを作る書式
変数.Select(ラムダ式)
0を数えるプログラム
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample { class Program { static void Main(string[] args) { int[] hp = { 420, 0, 600, 0, 1200 }; int num = 0; for(int i = 0;i < hp.Length; i++) { if(hp[i] == 0) { num++; } } Console.WriteLine(num); } } }
LINQを使うとこうなります。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sample { class Program { static void Main(string[] args) { int[] hp = { 420, 0, 600, 0, 1200 }; int num = hp.Where(n => n == 0).Count(); Console.WriteLine(num); } } }
プログラム内では1行で書いていますが、
下記をつなげて書いたものです。
var a = hp.Where(n => n ==0);
int num = a.Count
Whereメソッドの引数に(n => n == 0)というラムダ式を渡しています。
このラムダ式は引数nの値が0の時trueを返すメソッドと同じです。
配列の中から0と等しい値だけを取り出し{0,0}という結果を変数aに代入しています。
Whereメソッドにたいして、Countメソッドを使って要素数を調べます。
要素数を取得する書式
変数名.Count()
LINQのメソッド
メソッド名 | 役割 |
---|---|
Where(ラムダ式) | 条件を満たす要素をすべて返す |
Select(ラムダ式) | 各要素に処理を施して新しいデータを返す |
OrderBy(ラムダ式) | 昇順に並べ替えたデータを返す |
OrderByDecending(ラムダ式) | 降順に並べ替えたデータを返す |
Distinct() | 重複を除いたデータを返す |
Max() | 最大値を返す |
Min() | 最小値を返す |
Average() | 平均値を返す |
Sum() | 合計値を返す |
Count() | 要素数を返す |
All(ラムダ式) | すべての要素が条件式を満たしているかを判断する |
Any(ラムダ式) | 条件を満たす要素が含まれているか判断する |
終わりに
LINQを使えば長いコードを書かなくてもよくなりますね。
僕の頭でもなんとなく理解が出来た気がします。
ただ、for文とかに慣れているので、LINQを使いこなせるかといえば、
難しいかなぁと思ってしまいます。
でも慣れなきゃ。
時代が進むにつれて、プログラムも進化しているんです。
頑張らなきゃですね。
C#やUnityとは関係ないですが、
プログラミングとはなんぞやを教えてくれる本があります。
この本は文法より先に思考法を覚えるといった作りになっており、
プログラマが何を考えながらモノを作っているのかをゲームを作りながら教えてくれる本です。
プログラミングをする人は一度読んでおいて損はないと思います。
それではまた次回。
>引数の値が0ならtrue、そうでなければfalseを返すメソッドです。
引数の値が0より大きいならtrue、そうでなければfalseを返すメソッドです。
ほほう。間違えてましたか。すみません。
訂正ありがとうございます!!
蛇足ですが、引数の値が0以上なら、だと思います。
0以上でtrue, そうでなければflaseかと。
0より大きい、とするのであれば return n > 0;
ご指摘ありがとうございます!
まだまだ未熟で、不足等がありますが、
これからもよろしくお願いします。