问题描述
C#/.NET应用程序编程开发中,假如当前有一个泛型集合,如何使用LINQ获取这个泛型集合的最后N个元素?
方案一
使用LINQ的扩展方法Skip()
,如下:
collection.Skip(Math.Max(0, collection.Count() - N));
为了重复使用,我们也可以将其他封装成一个静态扩展方法,如下:
public static class MiscExtensions
{
public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int N)
{
return source.Skip(Math.Max(0, source.Count() - N));
}
}
调用示例:
var collection = new List<T>();
var lastElements = collection.TakeLast(5);
方案二
使用LINQ的扩展方法Reverse()
将列表反转,再使用Take()
方法取前N个元素,最后再将取出的子集合进行Reverse()
即可,扩展方法如下:
public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> coll, int N)
{
return coll.Reverse().Take(N).Reverse();
}
方案三
封装一个不使用LINQ的扩展方法,如下:
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;
}
}
调用示例:
IEnumerable<int> sequence = Enumerable.Range(1, 10000);
IEnumerable<int> last10 = sequence.TakeLast(10);
方案四
另一个不使用LINQ封装的扩展方法,如下:
public static class TakeLastExtension
{
public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int takeCount)
{
if (source == null) { throw new ArgumentNullException("source"); }
if (takeCount < 0) { throw new ArgumentOutOfRangeException("takeCount", "must not be negative"); }
if (takeCount == 0) { yield break; }
T[] result = new T[takeCount];
int i = 0;
int sourceCount = 0;
foreach (T element in source)
{
result[i] = element;
i = (i + 1) % takeCount;
sourceCount++;
}
if (sourceCount < takeCount)
{
takeCount = sourceCount;
i = 0;
}
for (int j = 0; j < takeCount; ++j)
{
yield return result[(i + j) % takeCount];
}
}
}
调用示例:
List<int> l = new List<int> {4, 6, 3, 6, 2, 5, 7};
List<int> lastElements = l.TakeLast(3).ToList();
方案五
使用LINQ的扩展方法SkipWhile
,如下:
public static IEnumerable<T> TakeLastN<T>(this IEnumerable<T> source, int n)
{
if (source == null)
throw new ArgumentNullException("Source cannot be null");
int goldenIndex = source.Count() - n;
return source.SkipWhile((val, index) => index < goldenIndex);
}
版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。
发表评论
登录用户才能发表评论, 请 登 录 或者 注册