LINQ:介绍 Take Last 运算符





4.00/5 (1投票)
LINQ:介绍 Take Last 运算符
前段时间,我需要检索满足某些条件的序列的最后几个项目,查看 Enumerable 类中可用的运算符,我注意到没有这样的运算符。
实现此目的的唯一方法是反转序列,获取满足条件的项,然后反转结果序列。像这样
sequence.Reverse().TakeWhile(criteria).Reverse();
看起来很简单,对吧?首先,我们调用 Reverse 方法来生成一个新序列,该序列与原始序列具有相同的项目,但顺序相反,然后我们调用 TakeWhile 方法来获取满足条件的第一个项目,然后再次调用 Reverse
方法来恢复项目的原始顺序。
这种方法的问题在于 Reverse
方法在以相反的顺序迭代其项目之前会缓冲整个序列 - 上面的代码使用了两次。这意味着迭代原始序列中的所有项目并缓冲所有项目,迭代满足条件的 resulting 序列的第一个项目并缓冲所有项目,最后,迭代该结果以生成最终序列。
如果您正在计数,您会得出结论,原始序列中的所有项目将被迭代一次,而结果序列中的项目将被迭代三次。如果原始序列很大,这会占用大量内存和时间。
如果您使用在选择标准评估中使用原始序列中项目索引的变体(^),则存在另一个问题。当我们反转项目的顺序时,索引将被反转,并且谓词必须考虑到这一点,如果您不知道原始序列中项目的数量,则这可能是不可能的。
一定有更好的方法,这就是我实现 Take Last 运算符的原因
名称 | 描述 | 示例 |
---|---|---|
TakeLast<TSource>(IEnumerable<TSource>) |
从序列的末尾返回指定数量的连续元素。 |
int[] grades = { 59, 82, 70, 56, 92, 98, 85 };
var topThreeGrades = grades
.OrderBy(grade => grade)
.TakeLast(3);
Console.WriteLine("The top three grades are:");
foreach (int grade in topThreeGrades)
{
Console.WriteLine(grade);
}
/*
This code produces the following output:
The top three grades are:
98
92
85
*/
|
TakeLastWhile<TSource>(IEnumerable<TSource>, Func<TSource, Boolean>) |
只要指定的条件为 |
string[] fruits =
{
"apple",
"passionfruit",
"banana",
"mango",
"orange",
"blueberry",
"grape",
"strawberry"
};
var query = fruits
.TakeLastWhile(fruit =>
string.Compare("orange",
fruit, true) != 0);
foreach (string fruit in query)
{
Console.WriteLine(fruit);
}
/*
This code produces the following output:
blueberry
grape
strawberry
*/
|
TakeLastWhile<TSource>(IEnumerable<TSource>, Func<TSource, Int32, Boolean>) |
只要指定的条件为 |
string[] fruits =
{
"apple",
"passionfruit",
"banana",
"mango",
"orange",
"blueberry",
"grape",
"strawberry"
};
var query = fruits
.TakeLastWhile((fruit, index) =>
fruit.Length >= index);
foreach (string fruit in query)
{
Console.WriteLine(fruit);
}
/*
This code produces the following output:
strawberry
*/
|
您可以在我的 CodePlex 项目中找到这些(以及更多)运算符,用于 LINQ 实用程序和运算符:PauloMorgado.Linq。