是否有更好的方法来获取每个项与谓词匹配的子序列?

Ria*_*Ria 4 c# linq

说我有一个IEnumerable.例如,{2,1,42,0,9,6,5,3,8}.

我需要获得与谓词匹配的项目的"运行".例如,如果我的谓词是

bool isSmallerThanSix(int number){...}
Run Code Online (Sandbox Code Playgroud)

我想获得以下输出:{{2,1},{0},{5,3}}

是否有内置功能可以实现这一目标?

到目前为止我有这个:

public static IEnumerable<IEnumerable<T>> GetSequences<T>(this IEnumerable<T> source,
      Func<T, bool> selector) {

        if (source == null || selector == null) {
            yield break;
        }

        IEnumerable<T> rest = source.SkipWhile(obj => !selector(obj));

        while (rest.Count() > 0) {
            yield return rest.TakeWhile(obj => selector(obj));
            rest = rest
                    .SkipWhile(obj => selector(obj))
                    .SkipWhile(obj => !selector(obj));
        }


    }
Run Code Online (Sandbox Code Playgroud)

这看起来很有效,但是我是在半夜写的,因此从星期二开始就效率低十五.是否有更好的,最好是内置(因此经过良好测试)的方式?

非常感谢你们的时间,

利雅.

Gar*_*ler 6

据我所知,没有一种构建方法.但是,Count在an上调用扩展方法IEnumerable效率不高,因为它必须枚举列表以获取计数.因此,我想出了具有相同效果的这一点.

public static IEnumerable<IEnumerable<T>> 
    GetSequences<T>(this IEnumerable<T> source, Func<T, bool> selector)
{
    // omitted null checks for brevity
    var list = new List<T>();

    foreach(var item in source)
    {
        if (selector.Invoke(item))
        {
            list.Add(item);
        }
        else if (list.Count > 0)
        {
            yield return list;
            list = new List<T>();
        }
    }

    if (list.Count > 0)
        yield return list;
}
Run Code Online (Sandbox Code Playgroud)

正如Jon Skeet所提到的那样,在这种情况下使用SkipWhileTakeWhile看起来效率也很低,因为它们会在迭代器上的迭代器上创建迭代器.您可以在调试示例时将其检查出来,当您逐步尝试查找下一个序列时会有点疯狂,即使示例很简单也是如此.