Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

C#辞典

  1. トップページ
  2. C#辞典
  3. Enumerable.Distinct() / Take() / Skip()

Enumerable.Distinct() / Take() / Skip()

シーケンスの重複除去・件数制限・スキップを行う LINQ の拡張メソッドです。ページング処理などでよく使われます。

構文
using System.Linq;

// 重複を除去します。
IEnumerable<T> unique = source.Distinct();

// 先頭から n 件取得します。
IEnumerable<T> top = source.Take(n);

// 先頭の n 件をスキップして残りを返します。
IEnumerable<T> rest = source.Skip(n);

// Take と Skip を組み合わせてページングします。
IEnumerable<T> page = source.Skip((page - 1) * pageSize).Take(pageSize);
メソッド一覧
メソッド概要
Distinct()重複を除いた要素を返します。
DistinctBy(keySelector).NET 6 以降。指定キーで重複を除いた要素を返します。
Take(count)先頭から指定件数の要素を返します。
TakeLast(count)末尾から指定件数の要素を返します。
TakeWhile(predicate)条件を満たす間だけ先頭から要素を返します。
Skip(count)先頭の指定件数をスキップして残りを返します。
SkipLast(count)末尾の指定件数を除いた要素を返します。
SkipWhile(predicate)条件を満たす間だけ先頭をスキップします。
Chunk(size).NET 6 以降。指定サイズのバッチ(配列)に分割します。
サンプルコード
using System;
using System.Collections.Generic;
using System.Linq;

List<int> numbers = new List<int> { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 };

// Distinct: 重複を除去します(初出の順序を保持)。
IEnumerable<int> unique = numbers.Distinct();
Console.WriteLine(string.Join(", ", unique)); // 3, 1, 4, 5, 9, 2, 6

// Take: 先頭 3 件を取得します。
IEnumerable<int> top3 = numbers.Take(3);
Console.WriteLine(string.Join(", ", top3));   // 3, 1, 4

// Skip: 先頭 3 件をスキップします。
IEnumerable<int> rest = numbers.Skip(3);
Console.WriteLine(string.Join(", ", rest));   // 1, 5, 9, 2, 6, 5, 3

// ページング: 1 ページ 3 件で 2 ページ目を取得します。
int pageSize = 3;
int pageNum  = 2;
IEnumerable<int> page = numbers.Skip((pageNum - 1) * pageSize).Take(pageSize);
Console.WriteLine(string.Join(", ", page));   // 1, 5, 9

// TakeWhile: 5 未満の間だけ先頭から取得します。
IEnumerable<int> tw = numbers.TakeWhile(n => n < 5);
Console.WriteLine(string.Join(", ", tw));     // 3, 1, 4

// .NET 6 以降: DistinctBy でオブジェクトの特定キーで重複除去します。
var people = new List<(string Name, int Age)>
{
    ("田中", 30), ("鈴木", 25), ("佐藤", 30),
};
var byAge = people.DistinctBy(p => p.Age);
foreach (var p in byAge) Console.WriteLine(p.Name);

// .NET 6 以降: Chunk でリストをバッチ分割します。
var chunks = Enumerable.Range(1, 10).Chunk(3);
foreach (var chunk in chunks)
    Console.WriteLine(string.Join(", ", chunk));
概要

『Distinct()』はデフォルトで参照型の場合は参照等価、値型の場合は値等価で比較します。カスタムオブジェクトで重複除去する場合は『IEqualityComparer<T>』を渡すか、.NET 6 以降では『DistinctBy()』でキーを指定すると簡潔に書けます。

『TakeWhile()』と『SkipWhile()』は先頭から評価するため、条件が途中で偽になった後の要素は条件を満たしていても処理されません。全体から抽出したい場合は『Where()』を使ってください。

シーケンスの生成には『Enumerable.Range() / Repeat() / Empty()』が役立ちます。リストへの変換は『Enumerable.ToList() / ToArray()』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。