【问题标题】:Linq: X objects in a rowLinq:连续 X 个对象
【发布时间】:2013-04-29 15:56:22
【问题描述】:

当列表按日期排序时,如果列表连续包含 x 个对象,我需要 linq 查询的帮助。

像这样:

myList.InARow(x => x.Correct, 3)

如果连续有 3 个属性正确 == true,则返回 true。

不知道该怎么做。

【问题讨论】:

    标签: c# arrays linq


    【解决方案1】:

    使用GroupAdjacent 扩展,您可以:

    var hasThreeConsecutiveCorrect 
        = myList.GroupAdjacent(item => item.Correct)
                .Any(group => group.Key && group.Count() >= 3);
    

    这是另一种使用Rollup 扩展(选择和聚合之间的交叉)的方式,它更节省空间:

    var hasThreeConsecutiveCorrect 
        = myList.Rollup(0, (item, sum) => item.Correct ? (sum + 1) : 0)
                .Contains(3);
    

    【讨论】:

    • 不用扩展也可以。
    • @VladimirFrolov:当然。实际上,我赞成你的(它类似于我使用的 Rollup 示例),但主要缺点是使用 Aggregate 意味着我们必须消耗整个序列,而 Rollup 不是这种情况。
    • 是的,聚合可能会更慢。
    【解决方案2】:

    linq 中没有任何东西可以轻松处理这种情况。但是创建自己的扩展方法是一件比较简单的事情。

    public static class EnumerableExtensions {
        public IEnumerable<T> InARow<T>(this IEnumerable<T> list, 
                                        Predicate<T> filter, int length) {
            int run = 0;
            foreach (T element in list) {
                if (filter(element)) {
                    if (++run >= length) return true;
                } 
                else {
                    run = 0;
                }
            }
            return false;
        }
    }
    

    【讨论】:

    • 一堆很好的答案。对于未来的开发人员来说,这将是最容易阅读的,所以我将使用这一。
    【解决方案3】:

    更新

    myList.Aggregate(0,
        (result, x) => (result >= 3) ? result : (x.Correct ? result + 1 : 0),
        result => result >= 3);
    

    通用版

    myList.Aggregate(0,
        (result, x) => (result >= length) ? result : (filter(x) ? result + 1 : 0),
        result => result >= length);
    

    【讨论】:

    • 这是Aggregate的巧妙运用!我喜欢它。
    • @recursive 我不同意。 Aggregate 的想法是,序列中的每个项目都代表结果的一部分,并且需要将它们组合成一个项目。这不是这样做的,因此与方法的设计相反,这会造成混乱并妨碍可读性,因为它没有使用Aggregate 来聚合数据,它只是使用Aggregate 而不是foreach,因为@ 987654328@ 有一个内部的foreach 和一个可以搭载的外部变量。明确地使用 foreach 会同样有效,并且更具可读性。
    • @Servy:我理解你的意思,但似乎有争议。可以假设运行长度从每个序列元素计算的结果。最困扰我的是它对序列的渴望消费。
    • @recursive 清除聚合值或“已完成”的概念(每一个都是此代码中的两个if 检查之一)与聚合的概念相反。无论项目的顺序如何,聚合也应该能够正常工作,这再次与聚合的概念相反。它甚至比仅使用foreach 节省的费用非常少,并且在保存这几个字符的可读性和敏感性方面损失了很多;这完全不值得。
    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 2015-06-23
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    相关资源
    最近更新 更多