コレクションが与えられた場合、そのコレクションの最後の N 要素を取得する方法はありますか? フレームワークにメソッドがない場合、これを行うための拡張メソッドを記述する最適な方法は何でしょうか?
ベストアンサー1
collection.Skip(Math.Max(0, collection.Count() - N));
このアプローチは、並べ替えに依存せずに項目の順序を維持し、複数の LINQ プロバイダー間で幅広い互換性を備えています。
負の数で呼び出さないように注意することが重要ですSkip
。Entity Framework などの一部のプロバイダーは、負の引数が渡されると ArgumentException を生成します。 の呼び出しはMath.Max
これをうまく回避します。
以下のクラスには、静的クラス、静的メソッド、キーワードの使用など、拡張メソッドに必要なすべての要素が含まれていますthis
。
public static class MiscExtensions
{
// Ex: collection.TakeLast(5);
public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int N)
{
return source.Skip(Math.Max(0, source.Count() - N));
}
}
パフォーマンスに関する簡単なメモ:
の呼び出しによってCount()
特定のデータ構造が列挙される可能性があるため、このアプローチでは、データが 2 回渡されるリスクがあります。これは、ほとんどの列挙可能オブジェクトでは問題になりません。実際、リスト、配列、さらには EF クエリでも、操作をCount()
O(1) 時間で評価するための最適化が既に存在しています。
しかし、前向きのみの列挙型を使用する必要があり、2回のパスを避けたい場合は、次のような1パスアルゴリズムを検討してください。ラッセ・V・カールセンまたはマーク・バイヤーズどちらのアプローチも、列挙中にアイテムを保持するために一時バッファを使用し、コレクションの末尾が見つかるとアイテムが返されます。