首页 > 解决方案 > 是否可以简化以下 Linq 表达式?

问题描述

我必须维护一个在两个集合的项目之间进行比较的代码

list1.Where(item1 => list2.Any(item2 => Cond1(item1,item2)) &&
    !list2.Any(item2 => Cond2(item1,item2)) 
)

我试图简化所有这些迭代,我想知道上面的代码是否等同于以下代码

list1.Where(item1 => list2.Any(item2 => Cond1(item1,item2) && !Cond2(item1,item2)))

这似乎更易于管理,所以我尝试了一些测试用例,初步结果还可以。您是否认为总体上是正确的,或者您能否发现需要第一个较长代码的情况(=与第二个较短的代码不同)?

编辑以反映评论

评论中的一些有趣的注释。

  1. Cond1当且仅当确定 的唯一键条件时,上述内容似乎是等价的list2,但在一般情况下当然不是这样。
  2. 正如Knoop 所指出的,颠倒这两个Any语句的顺序似乎更有效。

关于第 2 点,请考虑更现实的业务代码将是

list1.Where(item1 => list2.Any(item2 => Cond1(item1,item2)) &&
    !list2.Any(item2 => Cond1(item1,item2) && Cond2(item1,item2)) 
)

因为这里描述的典型业务问题是比较 2 个集合并查找缺失、匹配和不同的记录,后者(不同 - 但不缺失 - 记录)是问题中报告的内容

标签: c#linq

解决方案


此处描述的典型业务问题是比较 2 个集合并查找缺失、匹配和不同的记录,后者(不同 - 但不缺失 - 记录)是问题中报告的内容

如果您想要一个既实用又高效的解决方案,您可以使用 Enumerable.Aggregate LINQ 扩展方法,如类似答案中所建议的那样,将其包裹在Where第一个集合的外部内部list1

(bool allVerified, bool anyVerified) = 
    list2.Aggregate( 
        ValueTuple.Create(true, false), 
        (tuple, item) => ValueTuple.Create(
            tuple.Item1 && !(Cond1(item1,item) && Cond2(item1,item)), 
            tuple.Item2 || Cond1(item1, item)) );
return allVerified && anyVerified;

完整的片段小提琴在这里。


推荐阅读