のにっき

LINQの第一歩

LINQはムズかしい!

C#を勉強していて便利そうだけど難しそうな「LINQ」です。

このLINQは、リストや配列操作に非常に役に立つライブラリなのですが、
調べると必ず出てくる「匿名クラス」や「ラムダ式」など。。。
難しくて断念した方もいるのではないでしょうか?

しかし、サイトで勉強した使い方とは少し違った素人っぽい使い方で
LINQを使ってみたら、分かりやすく考えることができました。

初めてLINQを使う方が、LINQの浅い部分を使って便利だなーと感じる方法
LINQにハマるきっかけを書ければと思います。

リスト操作後は同じ型のリストに代入しよう!

LINQはあるListに対して操作を行うライブラリになります。
【例】
 ListAの中から、”ある文字”が含まれる要素だけ取得したい
 ListAの要素すべての末尾に、”ある文字”を追加したい

なので、基本的には
「ListAにLINQのメソッドを使ってListBにしたい!」と思った時に使います。
例文でよくあるのが

List<string> ListA = new List<string>();

ListA.Add("あ");
ListA.Add("い");

var ListB = ListA.Select( x => x + "ある文字" );

このように、「var」型に代入することが多いので
代入後のListBは何なんだ・・・?と思う方がいると思います。
素人の僕はこういう書き方で書きます

List<string> ListA = new List<string>();
List<string> ListB = new List<string>();

ListA.Add("あ");
ListA.Add("い");

ListB = ListA.Select( x => x + "ある文字" ).ToList();

もしくは

List<string> ListA = new List<string>();

ListA.Add("あ");
ListA.Add("い");

ListA= ListA.Select( x => x + "ある文字" ).ToList();

こうすれば、代入後のListBが分かりやすくなります。
そうです!LINQは代入後の型が不定なではなく
ListAの方に引っ張られるだけなので、ToListやToArrayが使えます。
ListAの内容を保持する必要が無ければ、
下の方のように上書きするとさらに分かりやすいです。

引数は、ラムダ式は最低限利用!基本は関数でどうにかする!

先ほどの例文にもありましたが、
Selectメソッドの引数部分※「Select()の中身」 について説明します。

基本的なことしかしない例文であればギリギリ意味が分かるのですが、
いざ自分のやりたいことを書こうと思ったらシドロモドロになっちゃいます。。。
そんな時は、()内に処理を書くのではなく、関数を呼びましょう。

【例】ListAの中から、”ある文字”が含まれる要素だけ取得する

    //========================================
    // LINQ処理で呼び出す関数
    //========================================
    public static bool IsMojiSonzai(string str_Surch, string str_Word)
    {
        bool bl_Ret = false;
        bl_Ret = str_Surch.Contains(str_Word);
        return bl_Ret;
    }
    //========================================
    // 要素を取得する関数
    //========================================
    public void Main()
    {
        List<string> ListA = new List<string>();
        List<string> ListB = new List<string>();

        ListA.Add("あ_ある文字");
        ListA.Add("い");

        ListB = ListA.Where(x => IsMojiSonzai( x, "ある文字" ) ).ToList();
    }

外部関数を使うことで、Whereメソッドの引数はすっきりできたと思います。
それでもラムダ式の記法が入ってしまうので最低限の説明を行います。

【例】ListA.Where(x => IsMojiSonzai( x, "ある文字" ))の説明
・x  ListA[ n番目 ]の要素
・=> この矢印以降に記述した関数がWhereメソッドの引数となる
IsMojiSonzai( x, "ある文字" ) この部分にやりたいことを別の関数で作成して呼ぶ!
・Where(x => IsMojiSonzai( x, "ある文字" )) 
 →「IsMojiSonzai」が「true」となる要素のみListB に格納するという意味になる
 
今回はWhereメソッドを使っていますが、どのメソッドでも同じ記法が使えます。
ラムダ式を最小限にして、外部関数を使用すれば
相当分かりやすくLINQを使用することができます

メソッドは「Select、Where」だけ覚えて使ってみる!

LINQを使ってList操作を行う際に、
この2つのメソッドは即戦力になること間違いなしです!
他のメソッドも便利なのは当たり前ですが、とりあえずこの2つのメソッドで
LINQというものが凄いものだと実感し、慣れて欲しいです。

  • Select

リストのすべての要素に処理を行うメソッドです。
【例】ListAの要素に"まんがな"が含まれていたら要素先頭に"関西人"
   含まれていなければ"東京人"を追加する

        //========================================
        // LINQ処理で呼び出す関数
        //========================================
        public static string SetCategory(string str_Serif)
        {
            string str_Ret = "";
            // 標準語判定
            if(str_Serif.Contains("まんがな"))
            {
                str_Ret = "関西人:"+ str_Serif;
            }
            else
            {
                str_Ret = "東京人:"+ str_Serif;
            }

            return str_Ret;
        }
        //========================================
        // セリフ分け関数
        //========================================
        private void Main()
        {

            List<string> ListA = new List<string>();
            List<string> ListB = new List<string>();

            ListA.Add("こんにちは");
            ListA.Add("こんにちまんがなでっせ");
            ListA.Add("わてでばんがな");
            ListA.Add("なんですかそれは?");

            ListB = ListA.Select(x => SetCategory(x)).ToList();
        }

【例】ListA.Select(x => SetCategory(x))の説明
ListBに、「 SetCategory( ListA[ n ] ) ※ n = ListAの全要素 」の戻り値を格納する
リストのすべての要素を引数として外部関数の処理を行い、
戻り値をListBに格納するイメージです。

  • Where

リストの要素に判定を行い、"true"となる要素を取得する
※"false"となる要素を排除するイメージです
使い方は
上記『【例】ListAの中から、”ある文字”が含まれる要素だけ取得する 』参照

LINQメソッドは併せて使用できる!

SelectとWhereを同時に使用してList操作を行うことも可能です
【例】ListAの要素に"まんがな"が含まれていたら要素先頭に"関西人"追加
   含まれていなければ要素から排除する

        //========================================
        // LINQ処理で呼び出す関数
        //========================================
        public static bool IsKansai(string str_Serif)
        {
            bool bl_Ret = false;
            // 標準語判定
            if (str_Serif.Contains("まんがな"))
            {
                bl_Ret = true;
            }
            else
            {
                bl_Ret = false;
            }

            return bl_Ret;
        }
        public static string SetCategory(string str_Serif)
        {
            string str_Ret = "";
            str_Ret = "関西人:"+ str_Serif;
            return str_Ret;
        }
        //========================================
        // セリフ分け関数
        //========================================
        private void Main()
        {

            List<string> ListA = new List<string>();
            List<string> ListB = new List<string>();

            ListA.Add("こんにちは");
            ListA.Add("こんにちまんがなでっせ");
            ListA.Add("わてでばんがな");
            ListA.Add("なんですかそれは?");

            ListB = ListA.Where(x => IsKansai(x)).Select(x => SetCategory(x)).ToList();
        }

「Where(x => IsKansai(x))」が「"まんがな"が含まれていなければ要素から排除する」
「Select(x => SetCategory(x))」が「含まれていたら要素先頭に"関西人"」の役割です
外部関数を呼ぶ形式なので、リストの選別・置換を1行で記入できます。
実処理部分がとてもすっきりするので見やすく修正しやすいと思います。

LINQはムズかしい!!!

以上が、僕が行ったLINQに慣れるための第一歩です。
上記の組み込み方を知るだけでもLINQが便利で使いやすいものであることが体感できます
しかし、上記の方法は
LINQメソッドの便利さをかなり制限しています!
ある程度LINQに慣れたら他のサイトを見ても
それなりに書いてる意味がわかる様になってます。
ラムダ式、匿名クラスの考え方」など本当に使えるようになった方がいい
便利要素はたくさんありますので
ぜひ、皆さんLINQについて勉強してみてください。