アマゾンバナーリンク

ディスプレイ広告

スポンサーリンク

LINQ関数一覧

こんにちは!ジェイです。前回LINQについて説明しましたが、今回はゲーム制作にも役立つLINQの関数一覧を作成しました。

目次

記事内広告

要素を取得する

Where

指定した条件のみの要素を取得する。

if文のような働きをします。

使い方

collection.Where(要素 => 抽出条件);

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<int> { 1, 2, 3, 4, 5, 6 };
            // 3より大きい要素のみ取り出す
            foreach (int x in list.Where(x => x > 3))
                Console.WriteLine(x);
        }
    }
}
実行結果

4
5
6

First, FirstOrDefault

対象となるデータから条件を満たす先頭にある1つの要素を抜き出す。

抜き出せなかった場合、Firstは例外が発生しますがFirstOrDefaultはその型の既定値を返します。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<string> { "ネコ", "にんげん", "犬", "にく"};
            string result = list.FirstOrDefault(x => x.Length == 2);
            Console.WriteLine(result);
        }
    }
}
実行結果

ネコ

Last, LastOrDefault

対象となるデータから条件を満たす最後尾にある1つの要素を抜き出す。

抜き出せなかった場合、Firstは例外が発生しますがFirstOrDefaultはその型の既定値を返します。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<string> { "ネコ", "にんげん", "犬", "にく"};
            string result = list.LastOrDefault(x => x.Length == 2);
            Console.WriteLine(result);
        }
    }
}
実行結果

にく

Single, SingleOrDefault

対象となるデータから条件を満たす唯一の要素を取得を抜き出す。

抜き出せなかった場合、Singleは例外が発生しますがSingleOrDefaultはその型の既定値を返します。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
            int result  = numbers.Single( x => x > 10 );
            Console.WriteLine(result);
        }
    }
}
実行結果

11

ElementAt, ElementAtOrDefault

対象となるデータから指定したインデックスの要素を取得を抜き出す。

抜き出せなかった場合、ElementAtは例外が発生しますがElementAtOrDefaultはその型の既定値を返します。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
            int result  = numbers.ElementAtOrDefault(3);
            Console.WriteLine(result);
        }
    }
}
実行結果

5

Skip, SkipWhile

指定した数以降の要素を取得する。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
            // 最初の3個とばして要素を取得する
            var result  = numbers.Skip(3);
            foreach (int x in result)
                Console.WriteLine(x);
        }
    }
}
実行結果

5
7
11

指定した条件以降の要素を取得する。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
            // 5より大きい数までとばして要素を取得する
            var result  = numbers.SkipWhile(x => x > 5);
            foreach (int x in result)
                Console.WriteLine(x);
        }
    }
}
実行結果

7
11

Take, TakeWhile

指定した数までの要素を取得する。

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
            // 最初の3個までの要素を取得する
            var result  = numbers.Take(3);
            foreach (int x in result)
                Console.WriteLine(x);
        }
    }
}
実行結果

1
2
3

指定した条件までの要素を取得する。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 1, 2, 3, 5, 7, 11 };
            // 5より大きい数になるまでの要素を取得する
            var result  = numbers.TakeWhile(x => x > 5);
            foreach (int x in result)
                Console.WriteLine(x);
        }
    }
}
実行結果

1
2
3
5

DefaultIfEmpty

配列やリストが空のときにデフォルトのなる要素を取得する。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> numbers = new List<int>();
            foreach (int number in numbers.DefaultIfEmpty())
            {
                Console.WriteLine(number);
            }
        }
    }
}
実行結果

要素を調べる

All

対象となる配列やリスト内の要素が、指定した条件を全て満たしているかを調べる。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            // 全ての要素は偶数かどうか
            bool reaultA = numbers.All( value => value % 2 == 0 );
            // 全ての要素は10未満かどうか
            bool reaultB = numbers.All( value => value < 10 );
            // 全ての要素は5以上かどうか
            bool reaultC = numbers.All( value => value >= 5 );
          System.Console.WriteLine( "全ての要素は偶数ですか  :{0}", reaultA );
          System.Console.WriteLine( "全ての要素は10未満ですか:{0}", reaultB );
          System.Console.WriteLine( "全ての要素は5以上ですか :{0}", reaultC );
        }
    }
}
実行結果

全ての要素は偶数ですか:False
全ての要素は10未満ですか:True
全ての要素は5以上ですか:False

Any

対象となる配列やリスト内の要素が、指定した条件を満たしている要素があるかを調べる。

配列やリストが空かどうか調べる

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbersA = new int[] { };
            int[] numbersB = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            bool reaultA = numbers.Any();
            bool reaultB = numbers.Any();
            // 5未満の要素はあるか
          System.Console.WriteLine( "numbersAは要素はありますか:{0}", reaultA );
          System.Console.WriteLine( "numbersBは要素はありますか:{0}", reaultB );
        }
    }
}
実行結果

numbersAは要素がありますか:False
numbersBは要素がありますか:True

条件を満たした要素があるかどうかを調べる

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            // 偶数の要素はあるか
            bool reaultA = numbers.Any( value => value % 2 == 0 );
            // 10以上の要素はあるか
            bool reaultB = numbers.Any( value => value < 10 );
            // 5未満の要素はあるか
            bool reaultC = numbers.Any( value => value >= 5 );
          System.Console.WriteLine( "偶数の要素はありますか  :{0}", reaultA );
          System.Console.WriteLine( "10以上の要素はありますか:{0}", reaultB );
          System.Console.WriteLine( "5未満の要素はありますか :{0}", reaultC );
        }
    }
}
実行結果

偶数の要素はありますか:True
10以上の要素はありますか:False
5未満の要素はありますか:True

Contains

対象となる配列やリスト内の要素に、指定した要素があるかを調べる。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            bool reaultA = numbers.Contains( 8 );
            bool reaultB = numbers.Contains( 3 );
            bool reaultC = numbers.Contains( 12 );
          System.Console.WriteLine( "8の要素はありますか:{0}", reaultA );
          System.Console.WriteLine( "3の要素はありますか:{0}", reaultB );
          System.Console.WriteLine( "12の要素はありますか:{0}", reaultC );
        }
    }
}
実行結果

8の要素はありますか:True
3の要素はありますか:True
12の要素はありますか:False

OfType

対象となる配列やリスト内の要素に、指定した型に変換できる要素があるかを調べる。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            ArrayList list = new ArrayList() { 1, 3, "2", 5.5f };
            // 各クラスに変換
            IEnumerable<int>    reaultInt       = list.OfType<int>();
            IEnumerable<string> reaultString    = list.OfType<string>();
            IEnumerable<float>  reaultFloat     = list.OfType<float>();
            IEnumerable<long>   reaultLong      = list.OfType<long>();
            System.Console.WriteLine( "list:{0}", list.Text() );
            System.Console.WriteLine( "intに変換できるもの   :{0}", reaultInt.Text() );
            System.Console.WriteLine( "stringに変換できるもの:{0}", reaultString.Text() );
            System.Console.WriteLine( "floatに変換できるもの :{0}", reaultFloat.Text() );
            System.Console.WriteLine( "longに変換できるもの  :{0}", reaultLong.Text() );
            // 入力待ち用
            System.Console.ReadKey();
        }
        public static string Text( this IEnumerable i_source )
        {
            string text = string.Empty;
            foreach( var value in i_source )
            {
                text += string.Format( "[{0}], ", value );
            }
            return text;
        }
    }
}
実行結果

list:[1], [3], [2], [5.5],
intに変換できるもの :[1], [3],
stringに変換できるもの:[2],
floatに変換できるもの :[5.5],
longに変換できるもの 

SequenceEqual

対象となる配列やリストが同じかどうか調べる

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[]       dataA   = new int[]     { 0, 1, 2, 3, 4, 5 };
            int[]       dataB   = new int[]     { 0, 1, 2, 4, 3, 5 };
            List<int>   dataC   = new List<int> { 0, 1, 2, 3, 4, 5 };

            // 要素は同じか?
            bool resultAB = dataA.SequenceEqual( dataB );
            bool resultAC = dataA.SequenceEqual( dataC );
            bool resultBC = dataB.SequenceEqual( dataC );

            System.Console.WriteLine( "dataA:{0}", dataA.Text() );
            System.Console.WriteLine( "dataB:{0}", dataB.Text() );
            System.Console.WriteLine( "dataC:{0}", dataC.Text() );

            System.Console.WriteLine( "A と B は同じですか:{0}", resultAB );
            System.Console.WriteLine( "A と C は同じですか:{0}", resultAC );
            System.Console.WriteLine( "B と C は同じですか:{0}", resultBC );
        }
    }
}
実行結果

A と B は同じですか:False
A と C は同じですか:True
B と C は同じですか:False

Count, LongCount

対象となる配列やリスト内の要素の数を調べる

CountとLongCountは同じで要素数がとても多くなる時のみLongCountを使います。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int reault = numbers.Count();
            System.Console.WriteLine( "numbersの要素数は{0}個です", reault);
        }
    }
}
実行結果

numbersの要素数は10個です。

条件に合った対象となる配列やリスト内の要素の数を調べる

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int reault = numbers.Count(x => x > 3);
            System.Console.WriteLine( "numbersの要素数は{0}です", reault);
        }
    }
}
実行結果

numbersの要素数は6個です

要素内で計算する

Max

対象となる配列やリストの中で一番大きい要素を取得する

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int reault = numbers.Max();
            System.Console.WriteLine( "numbersの要素で最大値は{0}です", reault);
        }
    }
}
実行結果

numbersの要素で最大値は9です

Min

対象となる配列やリストの中で一番小さい要素を取得する

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int reault = numbers.Min();
            System.Console.WriteLine( "numbersの要素で最小値は{0}です", reault);
        }
    }
}
実行結果

numbersの要素で最小値は0です

Average

配列やリストの平均値を取得する

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            float[] numbers = new float[] { 1.0f, 3.0f, 5.0f };
            float reault = numbers.Average();
            System.Console.WriteLine( "numbersの平均値は{0}です", reault);
        }
    }
}
実行結果

numbersの平均値は3.0です

Sum

配列やリストの要素の合計を取得する

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int reault = numbers.Sum();
            System.Console.WriteLine( "numbersの要素の合計は{0}です", reault);
        }
    }
}
実行結果

numbersの要素の合計は45です

Aggregate

配列やリスト内の情報を集計する

Aggregate()は、配列やリスト内の各要素に対して、指定した処理をすることができます。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers   = new int[] { 1, 2, 3, 4 };
            // 数字をすべて足したものを返す
            // 第一引数の"sum"に足された数値が入る
            int total = numbers.Aggregate( ( sum, next ) => sum += next );
            System.Console.WriteLine( "numbersの要素の合計は{0}です", reault);
        }
    }
}
実行結果

numbers:[1], [2], [3], [4],
total :10

Aggregate()の引数を指定の仕方はわかりずらいですよね。
上記のコードでAggregate()に指定している処理、( sum, next ) => sum += nextを見ていきましょう。

第二引数に、各要素が入ってきます。
今回の場合は、next1 ~ 4の値が入ってくるわけですね。
そして、第一引数には、ひとつ前の要素の処理のときに返した値が入ってきます。
値とは言っていますが、指定した型次第では、文字列だったり、クラスだったりします。

今回の場合のAggregate()の引数の流れを見ていくと

  • sum = 0, next = 1
  • sum = 1, next = 2
  • sum = 3, next = 3
  • sum = 6, next = 4

こんな感じになります。
そして、最後の要素の処理で返す値が、Aggregate()で返す値になります。

配列やリストを変換する

ToArray

リストなどを配列に変換する

ToList

配列などをリストに変換する

ToDictionary

配列からDictionaryを作る

AsEnumerable

IEnumerable型に変換する

Cast

cast(キャスト)は配列やリストを指定した型に変換する

Reverse

配列やリストの要素の順番を反転する

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5 };
            IEnumerable<int> reault = numbers.Reverse();
            foreach(var num in reault)
            {
                Console.WriteLine(num);
            }
        }
    }
}
実行結果

5
4
3
2
1
0

Distinct

重複した要素を除去して1つだけにする

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 0, 1, 1, 2, 2 };
            IEnumerable<int> reault = numbers.Distinct();
            foreach(var num in reault)
            {
                Console.WriteLine(num);
            }
        }
    }
}
実行結果

0
1
2

Select, SelectMany

配列やリスト内の要素を加工する

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 0, 1, 2, 3, 4, 5 };
            IEnumerable<int> reault = numbers.Select(x => x*2);
            foreach(var num in reault)
            {
                Console.WriteLine(num);
            }
        }
    }
}
実行結果

0
2
4
9
16
25

配列やリストを並べ替える

OrderBy, OrderByDescending

配列やリストを並べ替える(昇順)

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 2, 3, 0, 1, 5, 4 };
            IEnumerable<int> reault = numbers.OrderBy(x => x);
            foreach(var num in reault)
            {
                Console.WriteLine(num);
            }
        }
    }
}
実行結果

0
1
2
3
4
5

配列やリストを並べ替える(降順)

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = new int[] { 2, 3, 0, 1, 5, 4 };
            IEnumerable<int> reault = numbers.OrderByDescending(x => x);
            foreach(var num in reault)
            {
                Console.WriteLine(num);
            }
        }
    }
}
実行結果

5
4
3
2
1
0

ThenBy, ThenByDescending

配列やリストを複数ソートする時

ThenByは昇順、ThenByDescendingは降順

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
	class Program
	{
	    static void Main(string[] args)
	    {
	        List<Test1> list = new List<Test1>(new Test1[] {
	            new Test1(0, "b", 3, 1),
	            new Test1(1, "d", 1, 2),
	            new Test1(0, "a", 2, 3),
	            new Test1(1, "c", 2, 4),
	            new Test1(0, "e", 1, 5),
	        });
	 
	        // Flagを昇順、strIDを昇順、IDを降順として並べ替える
	        IOrderedEnumerable<Test1> sortList =
	            list.OrderBy(rec => rec.Flag).ThenBy(rec => rec.strID).ThenByDescending(rec => rec.ID);
	 
	        foreach (Test1 rec in sortList)
	        {
	            Console.WriteLine("{0},{1},{2},{3}", rec.Flag, rec.strID, rec.ID, rec.Rank);
	        }
	    }
	}
	
  class Test1
	{
	    public int Flag;
	    public int ID;
	    public string strID;
	    public int Rank;
	 
	    public Test1(int flag, string strId, int id, int rank)
	    {
	        this.Flag = flag;
	        this.ID = id;
	        this.strID = strId;
	        this.Rank = rank;
	    }
   }
}

配列やリスト内の要素を平均化する

GroupBy

配列やリストをグループ化する

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
  	{
        static void Main(string[] args)
	      {
            List<Class1> Test = new List<Class1>()
            {
                new Class1 {Kamoku = "国語", Tokuten = 90, Name = "東京太郎"},
                new Class1 {Kamoku = "数学", Tokuten = 80, Name = "東京太郎"},
                new Class1 {Kamoku = "英語", Tokuten = 70, Name = "東京太郎"},
                new Class1 {Kamoku = "理科", Tokuten = 40, Name = "東京太郎"},
                new Class1 {Kamoku = "社会", Tokuten = 55, Name = "東京太郎"},
 
                new Class1 {Kamoku = "国語", Tokuten = 60, Name = "東京次郎"},
                new Class1 {Kamoku = "数学", Tokuten = 50, Name = "東京次郎"},
                new Class1 {Kamoku = "英語", Tokuten = 80, Name = "東京次郎"},
                new Class1 {Kamoku = "理科", Tokuten = 60, Name = "東京次郎"},
                new Class1 {Kamoku = "社会", Tokuten = 90, Name = "東京次郎"},
 
                new Class1 {Kamoku = "国語", Tokuten = 50, Name = "東京三郎"},
                new Class1 {Kamoku = "数学", Tokuten = 70, Name = "東京三郎"},
                new Class1 {Kamoku = "英語", Tokuten = 65, Name = "東京三郎"},
                new Class1 {Kamoku = "理科", Tokuten = 40, Name = "東京三郎"},
                new Class1 {Kamoku = "社会", Tokuten = 80, Name = "東京三郎"},
            };
            var query = Test
                .GroupBy(x => x.Name) //名前でGroupByを行う
                .Select(x => new { Name = x.Key, Sum = x.Sum(y => y.Tokuten) }); //点数を集計する
 
            foreach (var group in query)
            {
                if (group.Name == "東京太郎")
                {
                    Console.WriteLine("東京太郎の合計点は{0}です" group.Sum);
                }
                if (group.Name == "東京次郎")
                {
                    Console.WriteLine("東京次郎の合計点は{0}です" group.Sum);
                }
                if (group.Name == "東京三郎")
                {
                    Console.WriteLine("東京三郎の合計点は{0}です" group.Sum);
                }
            }
        }
    }
}
実行結果

東京太郎の合計点数は335です
東京次郎の合計点数は340です
東京三郎の合計点数は305です

ToLookup

配列やリスト内の特定のデータでキーにしたデータを作る

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

namespace ConsoleApp1 {
  public enum Colors {
    紅,
    黄,
    白
  }
  public class Person {
    public Colors Color { get; set; }
    public string Name  { get; set; }
  }

  public class ToLookupTest {
    static void Main() {
      var list = new List<Person>();
      list.Add(new Person() { Color = Colors.紅, Name = "福沢祐巳"   });
      list.Add(new Person() { Color = Colors.黄, Name = "島津由乃"   });
      list.Add(new Person() { Color = Colors.白, Name = "藤堂志摩子" });
      list.Add(new Person() { Color = Colors.紅, Name = "小笠原祥子" });
      list.Add(new Person() { Color = Colors.黄, Name = "支倉玲"     });
      list.Add(new Person() { Color = Colors.紅, Name = "水野蓉子"   });
      list.Add(new Person() { Color = Colors.黄, Name = "鳥居江利子" });
      list.Add(new Person() { Color = Colors.白, Name = "佐藤聖"     });
      list.Add(new Person() { Color = Colors.紅, Name = "松平瞳子"   });
      list.Add(new Person() { Color = Colors.白, Name = "二条乃梨子" });
      list.Add(new Person() { Color = Colors.黄, Name = "有馬菜々"   });
      Console.WriteLine("----- 振り分け前 -----");
      for (int i = 0; i < list.Count; i++) {
        Console.WriteLine("[{0,2}] Color = {1}, Name = {2}", i, list[i].Color, list[i].Name);
      }
      // Color で振り分け
      var lookup = list.ToLookup(item => item.Color);
      Console.WriteLine("----- 振り分け後 -----");
      foreach (var group in lookup) {
        Console.WriteLine("キー : {0}", group.Key);
        var item = group.ToList();
        for (int i = 0; i < item.Count; i++) {
          Console.WriteLine("  [{0}] Color = {1}, Name = {2}", i, item[i].Color, item[i].Name);
        }
      }
    }
  }
}
実行結果

----- 振り分け前 -----
[ 0] Color = 紅, Name = 福沢祐巳
[ 1] Color = 黄, Name = 島津由乃
[ 2] Color = 白, Name = 藤堂志摩子
[ 3] Color = 紅, Name = 小笠原祥子
[ 4] Color = 黄, Name = 支倉玲
[ 5] Color = 紅, Name = 水野蓉子
[ 6] Color = 黄, Name = 鳥居江利子
[ 7] Color = 白, Name = 佐藤聖
[ 8] Color = 紅, Name = 松平瞳子
[ 9] Color = 黄, Name = 二条乃梨子
[10] Color = 白, Name = 有馬菜々
----- 振り分け後 -----
キー : 紅
  [0] Color = 紅, Name = 福沢祐巳
  [1] Color = 紅, Name = 小笠原祥子
  [2] Color = 紅, Name = 水野蓉子
  [3] Color = 紅, Name = 松平瞳子
キー : 黄
  [0] Color = 黄, Name = 島津由乃
  [1] Color = 黄, Name = 支倉玲
  [2] Color = 黄, Name = 鳥居江利子
  [3] Color = 黄, Name = 有馬菜々
キー : 白
  [0] Color = 白, Name = 藤堂志摩子
  [1] Color = 白, Name = 佐藤聖
  [2] Color = 白, Name = 二条乃梨子

振り分けのキーは任意の型が指定出来ます。

異なる配列やリスト同士を合体させる

Concat

配列やリストを連結する

コレクション同士を連結します。
重複するデータがある場合はそのまま連結されます。

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] array1 = { 1, 2, 3, };
            int[] array2 = { 2, 4, 6, };
            // LINQで連結する
            int[] concatenated = array1.Concat(array2).ToArray();
            foreach(var num in concatenated)
            {
                Console.WriteLine(num);
            }
        }
    }
}
実行結果

1
2
3
2
4
6

Union

配列やリストを連結する

コレクション同士を連結します。
重複するデータがある場合はそのまま連結されます。

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

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var listA = new string[] { "りんご", "ばなな", "ぶどう", "みかん" };
            var listB = new string[] { "さくらんぼ", "ばなな", "もも", "りんご" };

            var list = listA.Union(listB);

            foreach (var item in list)
            {
                System.Console.WriteLine(item);
            }
        }
    }
}
実行結果

りんご
ばなな
ぶどう
みかん
さくらんぼ
もも

Zip

別の型の配列やリストを合体して新しい型のシーケンスを作る

使い方

  • 第一引数はマージするシーケンス
  • 第二引数は2つのシーケンスの要素をマージする方法を指定する関数
using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] names = new string[] { "スライム", "ドラキー", "ももんじゃ" };
            int[] hp = new int[] { 5, 7, 10 };
            int[] exe = new int[] { 2, 4, 8, 10 ,12};
            var results = names.Zip(hp, (name, h) => new { Name = name, Hp = h });
            foreach(var item in results)
            {
                Console.WriteLine(item.Name);
                Console.WriteLine(item.Hp);
            }
            //要素数が少ない方に合わせられる
            var results2 = names.Zip(exe, (name, e) => new { Name = name, Exe = e });
            foreach(var item in results)
            {
                Console.WriteLine(item.Name);
                Console.WriteLine(item.Hp);
            }
        }
    }
}
実行結果

スライム
5
ドラキー
7
ももんじゃ
10

スライム
2
ドラキー
4
ももんじゃ
7

Join

別のデータの配列やリストと内部結合する

メソッドの引数は以下のようになっています。

  • 第1引数 ・・・ 結合するもう1つの配列 (配列B)
  • 第2引数 ・・・ 結合条件を指定するデリゲート (配列A側)
  • 第3引数 ・・・ 結合条件を指定するデリゲート (配列B側)
  • 第4引数 ・・・ 結合結果を作成するデリゲート

指定したキーに基づいて、コレクションを内部結合します。
以下の例では「社員.部署ID」と「部署.部署ID」をキーとして結合し、
1つのコレクションを作成しています。

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

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 従業員
            public class Employee
            {
                // 従業員ID
                public int Id { get; set;}
                // 部署ID
                public int DepartmentId { get; set;}
                // 従業員名
                public string Name { get; set;}
            }

            // 部署
            public class Department
            {
                // 部署ID
                public int Id { get; set;}
                // 部署名
                public string Name { get; set;}
            }

            // 従業員データ
            var employeeList = new List<Employee>
            {
                new Employee { Id = 100, Name = "佐藤", DepartmentId = 1 },
                new Employee { Id = 101, Name = "鈴木", DepartmentId = 2 },
                new Employee { Id = 102, Name = "高橋", DepartmentId = 3 },
                new Employee { Id = 103, Name = "田中", DepartmentId = 2 },
                new Employee { Id = 104, Name = "伊藤", DepartmentId = 1 },
                new Employee { Id = 105, Name = "渡辺", DepartmentId = 3 },
                new Employee { Id = 106, Name = "山本", DepartmentId = 1 },
            };

            // 部署データ
            var departmentList = new List<Department>
            {
                new Department { Id = 1, Name = "開発部" },
                new Department { Id = 2, Name = "研究部" },
                new Department { Id = 3, Name = "総務部" }
            };

            var list = employeeList.Join(departmentList, e => e.DepartmentId, d => d.Id, (e, d) => new
            {
                EmployeeId = e.Id,
                EmployeeName = e.Name,
                DepartmentName = d.Name
            });

            foreach (var item in list)
            {
                Console.WriteLine(item);
            }
        }
    }
}

実行結果

GroupJoin

別のデータの配列やリストと外部結合する

指定したキーに基づいて、コレクションを外部結合します。
以下の例では、「社員.部署ID」と「部署.部署ID」をキーとして結合しますが、
紐づくキーがない場合は部署にnullを設定するようにしています。

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

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 従業員
            public class Employee
            {
                // 従業員ID
                public int Id { get; set;}
                // 部署ID
                public int DepartmentId { get; set;}
                // 従業員名
                public string Name { get; set;}
            }

            // 部署
            public class Department
            {
                // 部署ID
                public int Id { get; set;}
                // 部署名
                public string Name { get; set;}
            }

            // 従業員データ
            var employeeList = new List<Employee>
            {
                new Employee { Id = 100, Name = "佐藤", DepartmentId = 1 },
                new Employee { Id = 101, Name = "鈴木", DepartmentId = 2 },
                new Employee { Id = 102, Name = "高橋", DepartmentId = null },
                new Employee { Id = 103, Name = "田中", DepartmentId = null },
                new Employee { Id = 104, Name = "伊藤", DepartmentId = 1 },
                new Employee { Id = 105, Name = "渡辺", DepartmentId = 3 },
                new Employee { Id = 106, Name = "山本", DepartmentId = 1 },
            };

            // 部署データ
            var departmentList = new List<Department>
            {
                new Department { Id = 1, Name = "開発部" },
                new Department { Id = 2, Name = "研究部" },
                new Department { Id = 3, Name = "総務部" }
            };

            var list = employeeList.GroupJoin(departmentList, e => e.DepartmentId, d => d.Id, (e, d) => new
            {
                EmployeeId = e.Id,
                EmployeeName = e.Name,
                Departments = d.DefaultIfEmpty()
                })
            .SelectMany(d => d.Departments, (e, d) => new
            {
                EmployeeId = e.EmployeeId,
                EmployeeName = e.EmployeeName,
                DepartmentName = d != null ? d.Name : "所属なし"
            });

            foreach (var item in list)
            {
                Console.WriteLine(item);
            }
        }
    }
}

実行結果

Except

配列やリストの差集合を取得する

左側のコレクション要素から、右側のコレクション要素を引きます。

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

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var listA = new string[] { "りんご", "ばなな", "ぶどう", "みかん" };
            var listB = new string[] { "さくらんぼ", "ばなな", "もも", "りんご" };

            var list = listA.Except(listB);

            foreach (var item in list)
            {
                System.Console.WriteLine(item);
            }
        }
    }
}
実行結果

ぶどう
みかん

Intersect

配列やリストの積集合を取得する

2つのコレクションのどちらにも含まれている要素のみ抽出します。

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

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var listA = new string[] { "りんご", "ばなな", "ぶどう", "みかん" };
            var listB = new string[] { "さくらんぼ", "ばなな", "もも", "りんご" };

            var list = listA.Intersect(listB);

            foreach (var item in list)
            {
                Console.WriteLine(item);
            }
        }
    }
}
実行結果

りんご
ばなな

新しいシーケンスを作る

Empty

空のシーケンスを生成する

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

namespace ConsoleApp1
{
    public static class Program
    {
        private class Parameter
        {
            public int      ID      { get; set; }
            public string   Name    { get; set; }

            public override string ToString()
            {
                return string.Format( "ID:{0}, Name:{1}", ID, Name );
            }
        }

        static void Main( string[] args )
        {
            IEnumerable<int>        intSequence         =  Enumerable.Empty<int>();
            IEnumerable<string>     stringSequence      =  Enumerable.Empty<string>();
            IEnumerable<Parameter>  parameterSequence   =  Enumerable.Empty<Parameter>();

            // 配列に変換する。
            int[]           intArray    = intSequence.ToArray();
            // リストに変換する。
            List<string>    stringList  = stringSequence.ToList();

            System.Console.WriteLine( "intArray 数:{0}",             intArray.Length );
            System.Console.WriteLine( "stringList 数:{0}",           stringList.Count );
            System.Console.WriteLine( "parameterSequence 数:{0}",    parameterSequence.Count() );
        }
    }
} 

実行結果

intArray 数:0
stringList 数:0
parameterSequence 数:0

Repeat

同じ要素が繰り返されるシーケンスを生成する

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

namespace ConsoleApp1
{
    public static class Program
    {
        static void Main( string[] args )
        {
            IEnumerable<string> strings =
            Enumerable.Repeat("I like programming.", 5);
 
            foreach (String str in strings)
            {
                Console.WriteLine(str);
            }
        }
    }
} 
実行結果

I like programming.
I like programming.
I like programming.
I like programming.
I like programming.

Range

指定した範囲の連続した整数のシーケンスを生成する

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

namespace ConsoleApp1
{
    public static class Program
    {
        static void Main( string[] args )
        {
            IEnumerable<int> intSequenceA = Enumerable.Range(1, 5);
            IEnumerable<int> intSequenceB = Enumerable.Range(-1, 3);
            IEnumerable<int> intSequenceC = Enumerable.Range(100, 4);
 
            foreach (String str in strings)
            {
                Console.WriteLine(str);
            }
        }
    }
} 
実行結果

intSequenceA:[1], [2], [3], [4], [5],
intSequenceB:[-1], [0], [1],
intSequenceC:[100], [101], [102], [103],

以上でLINQの関数すべてを一覧にしました。LINQはパフォーマンスの問題はありますが、無駄なループを減らせるので、特に初期化処理などはよく使えます。覚えておいて損はないので、ぜひ少しずつ使ってみましょう!

0