【问题标题】:Custom Inclusive TakeWhile(), is there a better way?自定义 Inclusive TakeWhile(),有没有更好的方法?
【发布时间】:2010-06-23 03:00:46
【问题描述】:

我编写了一个自定义 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检查的扩展方法

社区可以提供一些提示或重写吗? :)

【问题讨论】:

    标签: c# linq refactoring


    【解决方案1】:

    你是对的;这对延迟执行不友好(调用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;
            }
        }
    } 
    

    【讨论】:

    • 太棒了!我的一个更好的解决方案:)
    • 这太棒了。尤其是当您需要一个带有反转逻辑的 TakeWhile 时,即在谓词为 false 时获取所有内容。
    【解决方案2】:

    请不要直接回答这个问题。我想展示如何使用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 在这种情况下必须被反转两次。因此,请确保性能不会成为问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多