c#Enumerable采用谓词和结果限制的方法

gri*_*ave -1 c# linq ienumerable

在C#for IEnumerable中是否有任何扩展方法可以使用谓词返回集合中的项目,直到达到某个给定的限制为止?

例如:

string[] source = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var result = source.Take(2, item => item.EndsWith("e"));
// result == { "one", "three" }
Run Code Online (Sandbox Code Playgroud)

这个例子很容易反映这个想法,但是对于更复杂的逻辑,它可能是有用的,而不是评估集合中的每个项目.

我提出了以下解决方案,但也许.NET中已经有类似的东西了.

请勿使用以下代码 - 仅供参考

public static IEnumerable<T> Take<T>(this IEnumerable<T> enumerable,
    int count,
    Func<T, bool> predicate)
{
    if (enumerable == null)
    {
        yield break;
    }

    using (IEnumerator<T> iterator = enumerable.GetEnumerator())
    {
        var matchingCount = 0;
        while (matchingCount < count && iterator.MoveNext())
        {
            if (predicate(iterator.Current))
            {
                matchingCount++;
                yield return iterator.Current;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

优雅的解决方案 - 这也会做同样的事情:

public static IEnumerable<T> Take<T>(this IEnumerable<T> enumerable,
    int count,
    Func<T, bool> predicate)
{
    return enumerable.Where(predicate).Take(count);
}
Run Code Online (Sandbox Code Playgroud)

所以通过执行以下代码:

string[] source = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; 
var result = source
    .Where(n => { 
        Console.WriteLine("processing " + n); 
        return n.EndsWith("e"); 
    })
   .Take(2)
   .ToList();
Run Code Online (Sandbox Code Playgroud)

以下内容将记录在控制台中:

processing one
processing three
Run Code Online (Sandbox Code Playgroud)

希望这将有助于未来的任何人.

记住人:不要重新发明轮子.

Tit*_*mir 6

您可以结合TakeWhere:

var result = source.Where(item => item.Contains("e")).Take(2);
Run Code Online (Sandbox Code Playgroud)

Wherewhile会过滤集合,并Take在找到2个元素后停止迭代.由于这两个WhereTake懒惰也正在创建没有收藏,直到迭代,非常喜欢你的解决方案,可能会有性能上的损失,因为我们有两个LINQ运营商,但在大多数情况下,这不应该是一个问题.