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

2024-06-19

假设我有一个 IEnumerable。例如,{2,1,42,0,9,6,5,3,8}。

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

bool isSmallerThanSix(int number){...}

我想得到以下输出: {{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));
        }


    }

这似乎有效,但是我在半夜写的,因此从周二开始效率低下十五种。有没有更好的、最好是内置的(因此经过充分测试)的方法?

非常感谢大家抽出宝贵的时间

Ria.


据我所知,没有内置方法。然而,调用Count上的扩展方法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;
}

正如 Jon Skeet 提到的,使用SkipWhile and TakeWhile在这种情况下似乎效率也相当低,因为它们将在迭代器上创建迭代器。您可以检查一下,因为在调试示例时,当您逐步尝试找到下一个序列等时,即使示例很简单,它也会变得有点疯狂。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有更好的方法来获取每个项目与谓词匹配的子序列? 的相关文章

随机推荐