LoginSignup
56
72

More than 5 years have passed since last update.

C# LINQ サンプル集

Last updated at Posted at 2017-04-10

はじめに

LINQで遊ぶならLINQPad推奨。

※分類はなんとなくで決めてる

選択(フィルタ)

Where (filter, selection)

int[] nums2 = new[] { 1, 2, 3, 4, 5 };
IEnumerable<int> evenNums = nums2.Where(x => x % 2 == 0); 
// -> { 2, 4 }

Whereの省略

var nums = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// Where したあと Count する代わりに、
nums.Where(_ => _ % 2 == 0).Count();

// Count に直接 predicate を指定できる
nums.Count(_ => _ % 2 == 0);

// First や Last も同様
nums.First(_ => _ % 2 == 0);
nums.Last(_ => _ % 2 == 0);

射影

Select (map, projection)

string[] nums = new[] { "1", "2", "3", "4", "5" };
IEnumerable<int> numsInt = nums.Select(x => Int32.Parse(x));
// -> { 1, 2, 3, 4, 5 }

SelectMany

string[][] jaggedArray =
{
    new []{"a", "b", "c"},
    new []{"1", "2", "3"},
    new []{"い", "ろ", "は"},
};

IEnumerable<string> flatten = jaggedArray.SelectMany(x => x);
// -> {"a", "b", "c", "1", "2", "3", "い", "ろ", "は"}

参考:こんな風に使えるかも

// ローテートされた複数のログファイルをまとめて1つの配列に落とすサンプル
var logFiles = new[]
{
    @"C:\Logs\access.log",
    @"C:\Logs\access.log.1",
    @"C:\Logs\access.log.2",
};
var logLines = logFiles.SelectMany(file => File.ReadAllLines(file));

結合

Join, GroupJoin

var staffs = new[]
{
    new {StaffId = 1, DepartmentId = 1, Name = "Tanaka"},
    new {StaffId = 2, DepartmentId = 3, Name = "Suzuki"},
    new {StaffId = 3, DepartmentId = 2, Name = "Takahashi"},
    new {StaffId = 4, DepartmentId = 1, Name = "Sato"},
};
var departments = new[]
{
    new {DepartmentId = 1, Name = "Personnel"},
    new {DepartmentId = 2, Name = "Accounting"},
    new {DepartmentId = 3, Name = "General Affairs"},
};
var staffname_and_department =
        staffs.Join(
            departments,
            staff => staff.DepartmentId,
            department => department.DepartmentId,
            (staff, department) => new { Name = staff.Name, Department = department.Name });
var staffnames_for_department =
        departments.GroupJoin(
            staffs,
            department => department.DepartmentId,
            staff => staff.DepartmentId,
            (department, staff) => new { Department = department, Staffs = staff });

staffname_and_department (Join)

join.png

staffnames_for_department (GroupJoin)

groupjoin.png

グループ化

GroupBy

var employees = new[]
{
    new {Name = "Tanaka", Gender = "Male"},
    new {Name = "Suzuki", Gender = "Female"},
    new {Name = "Sato", Gender = "Male"},
    new {Name = "Tanaka", Gender = "Male"},
    new {Name = "Tanaka", Gender = "Female"},
};
var danjosuu = employees
               .GroupBy(e => e.Gender)
               .Select(g => new { Gender = g.Key, Count = g.Count() });

danjosuu (GroupBy)

Gender Count
Male 3
Female 2

要素を含んでるかを確かめる

All:要素すべてが条件に一致する

var numarray2 = new[] { 2, 4, 6 };

bool isAllEven = numarray2.All(x => x % 2 == 0); // true

Any:空ではない または 要素どれかが条件に一致する

var numarray3 = new[] { 1, 2, 3, 5, 7, 9 };

bool isNotEmpty = numarray3.Any(); // true

bool hasEvenNumber = numarray3.Any(x => x % 2 == 0); // true

Contains:含む

var numarray4 = new[] { 1, 4, 7, 10 };
bool contains4 = numarray4.Contains(4); // true

並びかえ

OrderBy, ThenBy, Reverse

var staffs2 = new[]
{
    new {Name = "Suzuki", Level = 10, Age = 19},
    new {Name = "Tanaka", Level = 5, Age = 27},
    new {Name = "Sato", Level = 10, Age = 32},
    new {Name = "Takahashi", Level = 3, Age = 30},
    new {Name = "Tamura", Level = 10, Age = 23},
};

staffs2.OrderByDescending(staff => staff.Level)// レベルが高い順
       .ThenBy(staff => staff.Age) // 次に若い順
       .Reverse(); // 逆順もできる

1つだけとりだす

First, Last, ElementAt

var nums3 = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int zero = nums3.First();
int nine = nums3.Last();
int five = nums3.ElementAt(5);

Single

var nums4 = new[] { 4 };
int four = nums4.Single();

DefaultIfEmpty, ~~OrDefault

var emptyArray = new string[] {};

//emptyArray.First(); // throws exception
emptyArray.FirstOrDefault(); // returns null
emptyArray.DefaultIfEmpty("default").FirstOrDefault(); // returns "default"

1部だけとりだす

Skip, Take

var nums5 = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var three2five = nums5.Skip(3).Take(3);
// -> { 3, 4, 5 }

SkipWhile, TakeWhile

var schedule = new[]
{
    new { Date = new DateTime(2017, 4, 11), IsWorkDay = true},
    new { Date = new DateTime(2017, 4, 12), IsWorkDay = true},
    new { Date = new DateTime(2017, 4, 13), IsWorkDay = true},
    new { Date = new DateTime(2017, 4, 14), IsWorkDay = true},
    new { Date = new DateTime(2017, 4, 15), IsWorkDay = false},
    new { Date = new DateTime(2017, 4, 16), IsWorkDay = false},
    new { Date = new DateTime(2017, 4, 17), IsWorkDay = true},
};

var tugihananrenkyuu = schedule
                       .SkipWhile(day => day.IsWorkDay)
                       .TakeWhile(day => !day.IsWorkDay)
                       .Count(); // 2

ほかのコレクションと何かする系

Concat:連結

string[] namesA = new[] { "Tanaka", "Suzuki" };
string[] namesB = new[] { "Sato", "Takahashi" };

IEnumerable<string> nameAB = namesA.Concat(namesB);
// -> { "Tanaka", "Suzuki", "Sato", "Takahashi" }

Zip:2つのシーケンスを同時に扱う

var idlist = new[] { 3, 2, 1 };
var namelist = new[] { "Tanaka", "Suzuki", "Sato" };
var idnames = idlist.Zip(namelist, (id, name) => new { Id = id, Name = name });

idnames (Zip)

Id Name
3 Tanaka
2 Suzuki
1 Sato

SequentialEqual:同じ順番?

var numarray = new[] { 1, 2, 3, 4, 5 };
var evenarray = new[] { 2, 4 };
bool sequentialEqual = numarray.Where(x => x % 2 == 0).SequenceEqual(evenarray); // true

集計

Sum, Max, Min, Average, Count, LongCount, Aggregate (fold, reduce)

var nums6 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
nums6.Sum(); // 55
nums6.Max(); // 10
nums6.Min(); // 1
nums6.Average(); // 5.5
nums6.Count(); // 10
nums6.LongCount(); // 10

// Example: ((((((((1 * 2) * 3) * 4) * 5) * 6) * 7) * 8) * 9) * 10)
nums6.Aggregate((x, y) => x * y); // 3628800 

集合

Distinct, Union, Intersect, Except

var primes = new[] { 2, 3, 5, 7, 11, 13 };
var oddNums = new[] { 1, 1, 3, 3, 5, 7, 9, 11, 13 };

var uniqueOdd = oddNums.Distinct();
// -> { 1, 3, 5, 7, 9, 11, 13 }

var primeOrOdd = primes.Union(oddNums);
// -> { 2, 3, 5, 7, 11, 13, 1, 9 }

var primeAndOdd = primes.Intersect(oddNums);
// -> { 3, 5, 7, 11, 13 }

var noPrimeOdd = oddNums.Except(primes);
// -> { 1, 9 }

変換

ToArray, ToList

var nums7 = new[] { 1, 2, 3, 4, 5, 6 };
int[] evenArray = nums7.Where(x => x % 2 == 0).ToArray();
List<int> oddList = nums7.Where(x => x % 2 != 0).ToList();

ToDictionary, ToLookup

var staffs3 = new[]
{
    new {StaffId = 1, DepartmentId = 1, Name = "Tanaka"},
    new {StaffId = 2, DepartmentId = 3, Name = "Suzuki"},
    new {StaffId = 3, DepartmentId = 2, Name = "Takahashi"},
    new {StaffId = 4, DepartmentId = 1, Name = "Sato"},
};
var id2name = staffs3.ToDictionary(staff => staff.StaffId, staff => staff.Name);
var depid2staff = staffs3.ToLookup(staff => staff.DepartmentId);

id2name (ToDictionary)

todict.png

depid2staff (ToLookup)

tolook.png

ToLookup と GroupBy の違い

ToLookupは即時評価される。GroupByは遅延評価。

Cast, OfType

ArrayList alist = new ArrayList() { "First", "Second", null, "Third" };
string[] arraycast = alist.Cast<string>().ToArray();
// -> { "First", "Second", null, "Third" }
string[] arrayoftype = alist.OfType<string>().ToArray();
// -> { "First", "Second", "Third" }

Cast と OfType の違い

  • Castはキャストに失敗した場合、例外をスローする。nullは残る。
  • OfTypeはキャスト可能な要素のみ取得する。nullは残らない。
56
72
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
72