【问题标题】:Is it possible to simplify the following Linq expression?是否可以简化以下 Linq 表达式?
【发布时间】:2020-04-30 15:37:16
【问题描述】:

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

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)))

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

编辑以反映 cmets

来自 cmets 的一些有趣的笔记。

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

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

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

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

【问题讨论】:

  • 第二条语句和第一条语句不一样。他们会在不同的情况下给出不同的结果
  • 第一个不编译。您不能两次声明item2。请提供实际运行的代码
  • 抱歉,错过了右括号。你完全正确
  • 说阿杰甘地是正确的。他们可以给出不同的结果。假设在第二个 Any item2 被称为 item3,现在更容易看到 item2item3 可以是不同的项目。所以基本上第一个说“list1中是否有任何项目在list2中有一个项目可以满足Cond1但list2中没有项目可以满足Cond2?”第二个会说“list1 中是否有任何项目,其中 list2 中有项目满足 Cond1 但不满足 Cond2”(因此它必须是 list2 中的相同项目)
  • 是的,但要使第一个为假,您需要迭代整个列表。在评估第一个元素之后,第二个可能已经是错误的。因此,如果期望男孩条件以相同的机会返回 true,这肯定是可证明的

标签: c# linq


【解决方案1】:

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

如果您想要一个既实用又高效的解决方案,您可以使用Enumerable.AggregateLINQ 扩展方法,正如在类似的answer 中所建议的那样,将外部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;

完整的 sn-p fiddle 在这里。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多