はじめに
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)
staffnames_for_department (GroupJoin)
グループ化
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)
depid2staff (ToLookup)
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は残らない。