我怎样才能避免这个集合迭代两次呢?

本文关键字:两次 迭代 集合 能避免 | 更新日期: 2023-09-27 18:08:26

注意:由于保密原因,我已经更改了集合的名称。

考虑以下代码:

o.Flag =
    o2.Collection1
        .Any(cpd => cpd.Collection1
            .Any(plc => plc.Collection1
                .Any(vd => vd.DetailedFlag))) ||
    o2.Collection1
        .Any(cpd => cpd.Collection2
            .Any(plc => plc.Collection1
                .Any(vd => vd.DetailedFlag)));

显然,我所做的是将详细标志扁平化为一个整体标志,但这段代码将o2.Collection1迭代两次。

我不明白SelectMany是如何完成这项工作的,因为标志在两个不同的集合上(即我没有将集合的集合扁平化)。

我怎样才能不那样做呢?

注:我感觉就像Jon Skeet,当我读到这篇文章时(使用LINQ来平化分层数据集-有一个警告)基本上说我被卡住了。但希望我读错了!

我怎样才能避免这个集合迭代两次呢?

如果集合具有相同的类型(或具有定义足够信息的公共基类型),则可以在查询中简单地将它们连接起来:

o.Flag =
    o2.Collection1
        .Any(cpd => cpd.Collection1.Concat(cpd.Collection2)
            .Any(plc => plc.Collection1
                .Any(vd => vd.DetailedFlag)));

请注意,这里的主要优点只是使查询更简单,并减少了代码重复。只要你的集合实际上是一个内存集合,它就不会对它的性能有任何明显的影响

如果它们的类型不兼容(或者与给出的示例不同,每个子集合的谓词存在细微差异),那么您可以管理的最佳方法是将两个子查询都拉到主集合的谓词中:

o.Flag =
    o2.Collection1
        .Any(cpd => cpd.Collection1
            .Any(plc => plc.Collection1
                .Any(vd => vd.DetailedFlag)) ||
            cpd.Collection2
            .Any(plc => plc.Collection1
                .Any(vd => vd.DetailedFlag)));

您可以使用单个迭代直到第一层,然后分支到两个单独的查询。

o.Flag =
    o2.Collection1
        .Any(cpd => cpd.Collection1
            .Any(plc => plc.Collection1
                .Any(vd => vd.DetailedFlag)) || 
             cpd.Collection2
            .Any(plc => plc.Collection1
                .Any(vd => vd.DetailedFlag)));