3 回答

TA貢獻1770條經(jīng)驗 獲得超3個贊
collection.Skip(Math.Max(0, collection.Count() - N));
這種方法保留了項目順序,而無需依賴任何排序,并且在多個LINQ提供程序之間具有廣泛的兼容性。
重要的是要注意不要以Skip負數(shù)呼叫。某些提供程序(例如,實體框架)在出現(xiàn)負參數(shù)時將產(chǎn)生ArgumentException。呼吁Math.Max巧妙地避免這種情況。
下面的類具有擴展方法的所有基本要素,這些要素是:靜態(tài)類,靜態(tài)方法和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));
}
}
關于性能的簡要說明:
因為對的調(diào)用Count()可能導致某些數(shù)據(jù)結(jié)構(gòu)的枚舉,所以此方法具有導致兩次通過數(shù)據(jù)的風險。對于大多數(shù)枚舉對象而言,這并不是真正的問題。實際上,已經(jīng)存在針對列表,數(shù)組甚至EF查詢的優(yōu)化,以評估Count()O(1)時間的操作。
但是,如果必須使用僅向前枚舉,并且希望避免進行兩次遍歷,請考慮像Lasse V. Karlsen或Mark Byers這樣描述的一次遍歷算法。這兩種方法都使用臨時緩沖區(qū)在枚舉時保存項目,一旦找到集合的末尾便會產(chǎn)生這些項目。

TA貢獻2019條經(jīng)驗 獲得超9個贊
注意:我錯過了您的問題標題“ 使用Linq”,因此我的答案實際上并未使用Linq。
如果要避免緩存整個集合的非惰性副本,則可以編寫一個使用鏈接列表執(zhí)行此操作的簡單方法。
以下方法將在原始集合中找到的每個值添加到鏈接列表中,并將鏈接列表縮小為所需的項目數(shù)。由于它通過遍歷整個集合始終將鏈接列表修剪為該項目數(shù),因此它將僅保留原始集合中最多N個項目的副本。
它不需要您知道原始集合中的項目數(shù),也不需要多次對其進行迭代。
用法:
IEnumerable<int> sequence = Enumerable.Range(1, 10000);
IEnumerable<int> last10 = sequence.TakeLast(10);
...
擴展方式:
public static class Extensions
{
public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> collection,
int n)
{
if (collection == null)
throw new ArgumentNullException("collection");
if (n < 0)
throw new ArgumentOutOfRangeException("n", "n must be 0 or greater");
LinkedList<T> temp = new LinkedList<T>();
foreach (var value in collection)
{
temp.AddLast(value);
if (temp.Count > n)
temp.RemoveFirst();
}
return temp;
}
}
- 3 回答
- 0 關注
- 910 瀏覽
添加回答
舉報