トップページに戻る    C#メモ    C#で作ったツール(コンソールアプリ)

C# LINQメモ


目次

001. Whereメソッド
002. GroupByメソッドとCountメソッド
003. Skipメソッド,Takeメソッド
004. Unionメソッド,Concatメソッド
005. FizzBuzz
006. Reverse,OrderBy,OrderByDescendingメソッド
007. 匿名classの配列
008. 組み合わせの列挙
009. 複数項目をSum
010. Select拡張メソッドでRowNum擬似列もどき
011. クエリ構文とメソッド構文の比較
012. TakeメソッドとSkipメソッド で要素数より大きい値を指定
013. IEnumerable<IGrouping<TKey, TSource>>の使用
014. Dictionary型同士でSequenceEqualで比較


001. Whereメソッド

using System.Linq;

class Program
{
    static void Main()
    {
        int[] work = { 1, 2, 3, 4, 5, 6 };
        var work2 = work.Where((x) => x > 3);
        foreach (var a in work2) {
            System.Console.WriteLine(a.ToString());
        }
    }
}

//出力結果
4
5
6


002. GroupByメソッドとCountメソッド

using System.Linq;

class Program
{
    static void Main()
    {
        int[] tmp = { 1, 1, 2, 2, 3, 3, 3, 4, 5 };
        var work = tmp.GroupBy(X => X).Select(X => new { X.Key, cnt = X.Count()});
        foreach (var a in work) {
            System.Console.WriteLine(a);
        }
    }
}

//出力結果
{ Key = 1, cnt = 2 }
{ Key = 2, cnt = 2 }
{ Key = 3, cnt = 3 }
{ Key = 4, cnt = 1 }
{ Key = 5, cnt = 1 }


003. Skipメソッド,Takeメソッド

using System.Linq;

class Program
{
    static void Main()
    {
        int[] tmp1 = { 1, 1, 2, 2, 3, 4, 5 };

        var work = tmp1.OrderBy(X => X)
                       .Skip(2)
                       .Take(3);
        foreach (int a in work) {
            System.Console.WriteLine(a);
        }
    }
}

//出力結果
2
2
3


004. Unionメソッド,Concatメソッド

using System.Linq;

class Program
{
    static void Main()
    {
        int[] tmp1 = { 1, 1, 2, 2, 3, 4, 5 };
        int[] tmp2 = { 8, 7 };
        int[] tmp3 = { 6, 7 };

        //ConcatがSQLのUnion all
        //UnionがSQLのUnion
        var work = tmp1.Concat(tmp2)
                   .Concat(tmp3);
        foreach (var a in work) {
            System.Console.WriteLine(a);
        }
    }
}

//出力結果
1
1
2
2
3
4
5
8
7
6
7


005. FizzBuzz

using System.Linq;

class Program
{
    static void Main()
    {
        var work = Enumerable.Range(1, 100)
            .Select(X =>
            {
                if (X % 3 == 0 && X % 5 == 0) return "FizzBuzz";
                if (X % 3 == 0) return "Fizz";
                if (X % 5 == 0) return "Buzz";
                return X.ToString();
            });
        foreach (var a in work) {
            System.Console.WriteLine(a);
        }
    }
}

//出力結果
1
2
Fizz
4
Buzz
以下略


006. Reverse,OrderBy,OrderByDescendingメソッド

using System.Linq;

class Program
{
    static void Main()
    {
        int[] arr = { 2, 4, 8, 3, 5, 7 };
        //arr = arr.Reverse().ToArray();
        arr = arr.OrderBy(X => X).ToArray();
        //arr = arr.OrderByDescending(X => X).ToArray();

        foreach (int each in arr) {
            System.Console.WriteLine(each);
        }
    }
}


007. 匿名classの配列

using System.Linq;

class Program
{
    static void Main()
    {
        var arr = new[] {new{ID = 1,Val = 3},
                         new{ID = 1,Val = 4},
                         new{ID = 1,Val = 5},
                         new{ID = 2,Val = 6},
                         new{ID = 2,Val = 7},
                         new{ID = 2,Val = 8},};
        var SQL = arr.GroupBy(X => X.ID)
                     .Select(X => new { X.Key, cnt = X.Count() });

        foreach (var each in SQL) {
            System.Console.WriteLine(each);
        }
    }
}


008. 組み合わせの列挙

using System;
using System.Linq;

class Program
{
    static void Main()
    {
        string line = "1,2 5,6,7";
        var with1 = line.Split(' ').Select(c => c.Split(',').AsEnumerable());
        var query = with1.Aggregate((xs, ys) => xs.SelectMany(_ => ys, (x, y) => x + '-' + y));
        foreach (var each in query) Console.WriteLine(each);
    }
}
//出力結果
//1-5
//1-6
//1-7
//2-5
//2-6
//2-7


009. 複数項目をSum

using System.Linq;

class Program
{
    static void Main()
    {
        var arr = new[] {new{Val1 = 1,Val2 = 3},
                         new{Val1 = 0,Val2 = 7},
                         new{Val1 = 4,Val2 = 5},
                         new{Val1 = 0,Val2 = 5},
                         new{Val1 = 5,Val2 = 2},
                         new{Val1 = 5,Val2 = 8},};

        var query = arr.GroupBy(A => 1)
                       .Select(A => new
                       {
                           sumVal1 = A.Sum(B => B.Val1),
                           sumVal2 = A.Sum(B => B.Val2),
                           cnt = A.Count()
                       });
        foreach (var each in query) {
            System.Console.WriteLine(each);
        }
    }
}
//出力結果
//{ sumVal1 = 15, sumVal2 = 30, cnt = 6 }


010. Select拡張メソッドでRowNum擬似列もどき

MSDN --- Select(TSource, TResult) メソッド

using System.Linq;

class Program
{
    static void Main()
    {
        var arr = new[] {new{Val1 = 1,Val2 = 3},
                         new{Val1 = 0,Val2 = 7},
                         new{Val1 = 4,Val2 = 5},
                         new{Val1 = 0,Val2 = 5},
                         new{Val1 = 5,Val2 = 2},
                         new{Val1 = 5,Val2 = 8},};
        var query = arr.Select((X, rn) => new { X.Val1, X.Val2, rn });
        foreach (var each in query) {
            System.Console.WriteLine(each);
        }
    }
}
//出力結果
//{ Val1 = 1, Val2 = 3, rn = 0 }
//{ Val1 = 0, Val2 = 7, rn = 1 }
//{ Val1 = 4, Val2 = 5, rn = 2 }
//{ Val1 = 0, Val2 = 5, rn = 3 }
//{ Val1 = 5, Val2 = 2, rn = 4 }
//{ Val1 = 5, Val2 = 8, rn = 5 }


011. クエリ構文とメソッド構文の比較

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    struct Struct1Def
    {
        internal int ID;
        internal string Name;
    }
    static List<Struct1Def> Struct1List = new List<Struct1Def>();

    struct Struct2Def
    {
        internal int ID;
        internal string Name;
    }
    static List<Struct2Def> Struct2List = new List<Struct2Def>();

    static void Main()
    {
        try {
            DataInit();

            Console.WriteLine("InnerJoin");
            Exec_InnerJoin();

            Console.WriteLine("LeftJoin");
            Exec_LeftJoin();
        }
        catch (Exception Ex) {
            Console.WriteLine(Ex.StackTrace);
        }
    }

    static void DataInit()
    {
        Struct1List.Add(new Struct1Def { ID = 1, Name = "111" });
        Struct1List.Add(new Struct1Def { ID = 2, Name = "222" });
        Struct1List.Add(new Struct1Def { ID = 6, Name = "333" });

        Struct2List.Add(new Struct2Def { ID = 1, Name = "AAA" });
        Struct2List.Add(new Struct2Def { ID = 2, Name = "BBB" });
        Struct2List.Add(new Struct2Def { ID = 9, Name = "CCC" });
    }

    static void Exec_InnerJoin()
    {
        //クエリ構文
        var QueryKoubun = from A in Struct1List
                          join B in Struct2List
                            on A.ID equals B.ID
                          select new { A.ID, A_Name = A.Name, B_Name = B.Name };

        foreach (var EachLine in QueryKoubun) {
            Console.WriteLine("ID = {0} , A_Name = {1} , B_Name = {2}",
                EachLine.ID, EachLine.A_Name, EachLine.B_Name);
        }

        //メソッド構文
        var MethodKoubun = Struct1List.Join(Struct2List, A => A.ID, B => B.ID,
            (A, B) => new { A.ID, A_Name = A.Name, B_Name = B.Name });

        if (MethodKoubun.SequenceEqual(QueryKoubun) == false)
            throw new Exception("クエリ構文とメソッド構文の結果が違います");
    }

    static void Exec_LeftJoin()
    {

        //クエリ構文
        var QueryKoubun = from A in Struct1List
                          join B in Struct2List
                            on A.ID equals B.ID into tmp1
                          from tmp2 in tmp1.DefaultIfEmpty(
                          new Struct2Def { ID = A.ID, Name = "Null" })
                          select new
                          {
                              A.ID,
                              A_Name = A.Name,
                              B_Name = tmp2.Name
                          };

        foreach (var EachLine in QueryKoubun) {
            Console.WriteLine("ID = {0} , A_Name = {1} , B_Name = {2}",
                EachLine.ID, EachLine.A_Name, EachLine.B_Name);
        }

        //メソッド構文
        var MethodKoubun = Struct1List.GroupJoin(Struct2List, A => A.ID, B => B.ID,
                        (A, B) => new
                        {
                            A.ID,
                            A_Name = A.Name,
                            Tmp = B.DefaultIfEmpty(
                            new Struct2Def { ID = A.ID, Name = "Null" })
                        }).SelectMany(A => A.Tmp,
                        (A, B) => new
                        {
                            A.ID,
                            A.A_Name,
                            B_Name = B.Name
                        });

        if (MethodKoubun.SequenceEqual(QueryKoubun) == false)
            throw new Exception("クエリ構文とメソッド構文の結果が違います");
    }
}
//出力結果
//InnerJoin
//ID = 1 , A_Name = 111 , B_Name = AAA
//ID = 2 , A_Name = 222 , B_Name = BBB
//LeftJoin
//ID = 1 , A_Name = 111 , B_Name = AAA
//ID = 2 , A_Name = 222 , B_Name = BBB
//ID = 6 , A_Name = 333 , B_Name = Null


012. TakeメソッドとSkipメソッド

TakeメソッドやSkipメソッドで、要素数より大きい数を指定しても、例外は発生しない。

using System;
using System.Linq;

class Program
{
    static void Main()
    {
        Console.WriteLine("出力1");
        foreach (int EachInt in Enumerable.Range(1, 5).Take(100))
            Console.WriteLine(EachInt); 
        
        Console.WriteLine("出力2");
        foreach (int EachInt in Enumerable.Range(1, 5).Skip(100))
            Console.WriteLine(EachInt);
        
    }
}

//出力結果
出力1
1
2
3
4
5
出力2


013. IEnumerable<IGrouping<TKey, TSource>>の使用

GroupByメソッドの結果は、IEnumerable<IGrouping<TKey, TSource>> という列挙になり、
その列挙に対して、WhereメソッドやMaxメソッドなどを使うことができます。

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        int[] wkArr = { 1, 1, 1, 1, 2, 3, 3, 3 };

        //集約関数のネストもどき
        int Query1 = wkArr.GroupBy(X => X).Max(A => A.Count());
        Console.WriteLine("CountのMax={0}", Query1);

        //Having句もどき
        var Query2 = wkArr.GroupBy(X => X).Where(X => X.Count() > 1)
            .Select(X => new { X.Key, cnt = X.Count() });
        foreach (var EachTokumei in Query2) {
            Console.WriteLine("{0}の件数={1}",
                EachTokumei.Key, EachTokumei.cnt);
        }
    }
    //出力結果
    //CountのMax=4
    //1の件数=4
    //3の件数=3
}


014. Dictionary型同士でSequenceEqualで比較

キーでソートすれば、要素も含めて比較できる

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        var CntDictA = new Dictionary<int, int>();
        var CntDictB = new Dictionary<int, int>();

        CntDictA[1] = 11;
        CntDictA[2] = 22;
        CntDictA[3] = 33;
        
        CntDictB[3] = 33;
        CntDictB[1] = 11; 
        CntDictB[2] = 22;

        if (CntDictA.OrderBy(pX => pX.Key).SequenceEqual(CntDictB.OrderBy(pX => pX.Key))) {
            Console.WriteLine("Yes");
        }
        else {
            Console.WriteLine("No");
        }
    }
}