我编写了一个自定义LINQ扩展方法,它将TakeWhile()
方法扩展为包含,而不是在谓词为false时将其排除。
public static IEnumerable<T> TakeWhile<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool inclusive)
{
source.ThrowIfNull("source");
predicate.ThrowIfNull("predicate");
if (!inclusive)
return source.TakeWhile(predicate);
var totalCount = source.Count();
var count = source.TakeWhile(predicate).Count();
if (count == totalCount)
return source;
else
return source.Take(count + 1);
}
虽然这有效,但我确信有更好的方法。我很确定这在延迟执行/加载方面不起作用。
ThrowIfNull()
是ArgumentNullException
检查的扩展方法
社区可以提供一些提示或重写吗? :)
答案 0 :(得分:12)
你是对的;这对延迟执行不友好(调用Count
需要完整枚举源代码。)
然而,你可以这样做:
public static IEnumerable<T> TakeWhile<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool inclusive)
{
foreach(T item in source)
{
if(predicate(item))
{
yield return item;
}
else
{
if(inclusive) yield return item;
yield break;
}
}
}
答案 1 :(得分:0)
直接回答问题。我想展示如何使用SkipWhile
模拟包含性的TakeWhile
逻辑。
IEnumerable<string> list = new List<string> { "1", "2", "3", "4", "5" };
var result = list
.Reverse()
.SkipWhile(item => item != "3")
.Reverse();
// result will be {"1", "2", "3"}
但是请注意,以这种方式执行效率会较低,因为在这种情况下,list
实际上必须反转两次。因此,请确保性能不会成为问题。