(僕の周りで)あまり見かけないけど、使いこなせれば強力な LINQ メソッドの紹介です。

Zip

2つのシーケンスをインデックス順にマージして一つのシーケンスにします。

int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" }; 

var zipped = numbers.Zip(
    words,
    (n, w) => $"{n} {w}"
);

foreach (var item in zipped)
    Console.WriteLine(item);
1 one
2 two
3 three

はみ出る要素は無視されます。


Union Intersect Except

Unionは2つのシーケンスの少なくともどちらかに含まれている要素(和集合)のシーケンスを返します。

string[] langs1 = { "C#", "Rust", "Elixir", "Swift", "Kotlin", };
string[] langs2 = { "Rust", "Clojure", "C#", "OCaml", };

var union = langs1.Union(langs2);

foreach (var lang in union)
    Console.Write($"{lang} ");
C# Rust Elixir Swift Kotlin Clojure OCaml

Intersectは2つのシーケンスのどちらにも含まれる要素(積集合)のシーケンスを返します。

string[] langs1 = { "C#", "Rust", "Elixir", "Swift", "Kotlin", };
string[] langs2 = { "Rust", "Clojure", "C#", "OCaml", };

var intersect = langs1.Intersect(langs2);

foreach (var lang in intersect)
    Console.Write($"{lang} ");
C# Rust

Exceptは対象のシーケンスからもう一方のシーケンスに属する要素を取り除いたシーケンスを返します。

 string[] langs1 = { "C#", "Rust", "Elixir", "Swift", "Kotlin", };
 string[] langs2 = { "Rust", "Clojure", "C#", "OCaml", };

 var except = langs1.Except(langs2);

 foreach (var lang in except)
     Console.Write($"{lang} ");
Elixir Swift Kotlin

シーケンスの取り除かれる側と取り除く側を入れ替えると、結果も変わります。

string[] langs1 = { "C#", "Rust", "Elixir", "Swift", "Kotlin", };
string[] langs2 = { "Rust", "Clojure", "C#", "OCaml", };

var except = langs2.Except(langs1);

foreach (var lang in except)
    Console.Write($"{lang} ");
Clojure OCaml

ToDictionary ToLookup

ToDictionaryはシーケンスや配列などをDictionaryに変換します。
Dictionary型に変換することでキーで高速に値にアクセスできます。

以下のようなBookクラスのリストがあるとします。

var books = new List<Book>
{
    new Book {
        ISBN = "ISBN● - AAAA - BBBB - C",
        Title = "タイトル",
        Author = "著者名",
        PublishedYear = 2000
    },
    new Book {  },
    new Book {  },
    
};
// ISBN をキー、値を Book オブジェクトとする Dictionary を作る
var bookDict = books.ToDictionary(b => b.ISBN);

// 値を指定するには、第2引数にラムダ式を与える
var bookDict = books.ToDictionary(b => b.ISBN, b => b.Title);

ToLookupはシーケンスや配列などをILookup型に変換します。
Dictionaryはキーに対し1つの値が割り当てられますが、
ILookUpはキーに対しコレクションが割り当てられます。

// 発行年をキーとし、Book オブジェクトのコレクションが値となる ILookup を作成する
var lookup = books.ToLookup(b => b.PublishedYear);
lookup[2000] // => 発行年が2000年の book オブジェクト一覧が返る

// 第二引数にラムダ式を与えることで、値を指定できる
var lookup = books.ToLookup(b => b.PublishedYear, b => b.Title);

ToLookupはGroupByとよく似ていますが、ToLookupは即時実行、GroupByは遅延評価です。
ToLookupならlookup[2000]のようにインデクサでアクセスできます。

値にリストを持つDictionaryを作る場合にはGroupByとToDictionaryを使います。
ToLookUpとToDcitinaryを組み合わせると2度ループが回ってしまいます。

// ToLookup と ToDictionary で2度ループが回る
var dic = books
    .ToLookup(b => b.PublishedYear)
    .ToDictionary(
        group => group.Key,
        group => group.ToList()
    );

// GroupBy と ToDictionary なら ループが回るのは ToDictionary の一度だけ
var dic = books
    .GroupBy(b => b.PublishedYear)
    .ToDictionary(
        group => group.Key,
        group => group.ToList()
    );

Distinct

メジャーかもしれませんが、僕の周りではあまり見ないので載せます。
シーケンスから重複した要素を削除したシーケンスを返します。

int[] ints = { 1, 2, 3, 4, 3, 2, 2, 5, 4 };
var distinct = ints.Distinct();
foreach (var n in distinct)
    Console.Write($"{n} ");
1 2 3 4 5

GroupJoin

2つのシーケンスをグルーピングするGroupByと、
2つのシーケンスを結合するJoinを、同時にやってしまうメソッドです。

以下のような漫画雑誌と漫画のリストがあるとします。

var magazines = new[]
{
    new { Name = "ジャンプ" },
    new { Name = "サンデー"},
    new { Name = "チャンピオン" },
};
var myComics = new[]
{
    new { Title = "グラップラー刃牙", Publication = "チャンピオン" },
    new { Title = "スラムダンク", Publication = "ジャンプ" },
    new { Title = "HUNTER×HUNTER", Publication = "ジャンプ" },
    new { Title = "名探偵コナン", Publication = "サンデー" }
};

上記2つのリストを結合し、漫画雑誌毎に漫画を振り分けます。

var groups = magazines.GroupJoin(
    myComics,
    magazine => magazine.Name,
    comic => comic.Publication,
    (magazine, comics) => new
    {
        Magazine = magazine.Name,
        Comics = comics
    });

foreach (var group in groups)
{
    Console.WriteLine($"{group.Magazine}:");
    foreach (var comic in group.Comics)
        Console.WriteLine($"  - {comic.Title}");
}
ジャンプ:
  - スラムダンク
  - HUNTER×HUNTER
サンデー:
  - 名探偵コナン
チャンピオン:
  - グラップラー刃牙

まとめ

LINQ には便利なメソッドがたくさんあります。
普段よく使うもの以外にもハマるとシーケンス・コレクション操作を強力にサポートしてくれるものがたくさんあるので、ぜひ使いこなしたいです。

广告
将在 10 秒后关闭
bannerAds