シーケンス先頭からのデータ取得
C#のLINQ(Language Integrated Query)には、コレクションから特定の条件でデータを抽出するメソッドが多数用意されています。その中でも、リストや配列の「先頭から」特定の範囲を取得したい場合に利用されるのが Take と TakeWhile です。
ページング処理(1ページ目だけを表示するなど)や、条件が崩れるまでの連続データを取得する際に非常に役立ちます。
この記事では、これら2つのメソッドの機能と、よく混同される Where メソッドとの動作の違いについて解説します。
Take(int count):指定した数だけ取得
Take メソッドは、シーケンスの先頭から、引数で指定した count 個の要素を取得します。
非常に単純なメソッドですが、データの「上位N件」を取得したい場合や、大量のデータからサンプルとして最初の数件だけを処理したい場合に最適です。
- 指定した数がコレクションの要素数より多い場合、あるだけの要素(全要素)が返されます。エラーにはなりません。
- 0以下の数を指定した場合、空のシーケンスが返されます。
コード例:上位3件のスコアを取得
点数の高い順に並んだリストから、トップ3(表彰対象)を抽出する例です。
using System;
using System.Collections.Generic;
using System.Linq;
public class TakeExample
{
public static void Main()
{
// 降順(高い順)にソートされているスコアリスト
var scores = new List<int> { 98, 95, 92, 88, 85, 70 };
// 先頭から 3つ だけ取得する
var topThree = scores.Take(3);
Console.WriteLine("--- 上位3名のスコア ---");
Console.WriteLine(string.Join(", ", topThree));
}
}
出力結果:
--- 上位3名のスコア ---
98, 95, 92
TakeWhile(predicate):条件を満たす間だけ取得
TakeWhile メソッドは、シーケンスの先頭から要素を順に評価し、指定した条件(述語)が true である間、要素を取得し続けます。
条件が一度でも false になると、そこで処理は打ち切られます。それ以降の要素が条件を満たしていたとしても、それらは取得されません。
コード例:黒字が続いた期間を取得
日毎の収支データ(配列)があり、赤字(マイナス)が出るまでの「連続黒字記録」を取得する例です。
using System;
using System.Collections.Generic;
using System.Linq;
public class TakeWhileExample
{
public static void Main()
{
// 日毎の収支(プラスは黒字、マイナスは赤字)
// 4日目に -200 (赤字) が発生している
var dailyProfits = new[] { 5000, 3200, 1500, -200, 6000, 4500 };
// 条件: 収支が 0 以上 (黒字) であること
// -200 が現れた時点で条件不一致となり、そこで抽出は終了する
var continuousProfits = dailyProfits.TakeWhile(p => p >= 0);
Console.WriteLine("--- 赤字になるまでの黒字データ ---");
Console.WriteLine(string.Join(", ", continuousProfits));
}
}
出力結果:
--- 赤字になるまでの黒字データ ---
5000, 3200, 1500
リストの後半にある 6000 や 4500 は条件を満たしていますが、TakeWhile は -200 でストップするため、結果には含まれません。
重要:Where と TakeWhile の違い
TakeWhile は、フィルタリングを行う Where メソッドと混同されがちですが、その動作は明確に異なります。
Where: リストの最後まですべての要素をチェックし、条件に合うものをすべて抽出します。TakeWhile: 先頭からチェックし、条件に合わない要素が出た時点で即座に終了します。
比較コード
var numbers = new[] { 1, 2, 3, 0, 4, 5 };
// Where: 0 以外のすべての数 (0 だけが除外される)
var whereResult = numbers.Where(n => n > 0);
// 結果: 1, 2, 3, 4, 5
// TakeWhile: 0 が出た時点で終了 (4, 5 は無視される)
var takeWhileResult = numbers.TakeWhile(n => n > 0);
// 結果: 1, 2, 3
ソート済みのデータに対して「ある閾値までのデータ」を取得する場合、Whereを使うと全件走査になりますが、TakeWhileを使えば条件不一致の時点でループが止まるため、パフォーマンス面でも有利になる場合があります。
まとめ
Take(n): 個数を指定して、先頭からデータを切り出す場合に使用します。(ページングやランキング表示など)TakeWhile(condition): 条件を指定して、その条件が継続している期間のデータを取得する場合に使用します。(連続記録の抽出や、ソート済みデータの範囲抽出など)
データの並び順が結果に直結するため、これらのメソッドを使用する際は、データの順序が意図通りになっているかを事前に確認することが重要です。
