【问题标题】:Linq select objects in list where exists IN (A,B,C)Linq选择列表中存在的对象(A,B,C)
【发布时间】:2012-12-24 19:22:24
【问题描述】:

我有一个orders 的列表。
我想根据一组订单状态选择orders

所以本质上是select orders where order.StatusCode in ("A", "B", "C")

// Filter the orders based on the order status
var filteredOrders = from order in orders.Order
                     where order.StatusCode.????????("A", "B", "C")
                     select order;

【问题讨论】:

  • 感谢所有这么快回答的人。 Esp 用于 lambda 解决方案。我还没有对 lambda 表达式做过任何事情。我假设我会做一个不包含使用 (o => !(statuses.Contains(o.OrderHeaderOrderStatusCode)))

标签: c# linq list linq-to-objects exists


【解决方案1】:

注意:这是 LINQ to objects,我不能 100% 确定它是否适用于 LINQ to entity,而且现在没有时间检查它。其实把它翻译成x in [A, B, C]并不难,但你必须自己检查。

因此,您可以使用 Any 代替 Contains 代替代码中的 ????,它更符合 LINQ-你好:

// Filter the orders based on the order status
var filteredOrders = from order in orders.Order
                     where new[] { "A", "B", "C" }.Any(s => s == order.StatusCode)
                     select order;

这与你从 SQL 中知道的相反,这就是为什么它不那么明显。

当然,如果你喜欢流畅的语法,这里是:

var filteredOrders = orders.Order.Where(order => new[] {"A", "B", "C"}.Any(s => s == order.StatusCode));

在这里,我们再次看到了 LINQ 的一个惊喜(比如 Joda-speech 将 select 放在最后)。然而,从这个意义上说,它检查列表(集合、集合)中是否至少有一个项目(即 any)与单个值匹配是很合乎逻辑的。

【讨论】:

    【解决方案2】:

    请注意,.Contains() 将匹配任何子字符串,包括您不期望的字符串。例如。 new[] { "A", "B", "AA" }.Contains("A") 将返回您可能不想要的 A 和 AA。我已经被它咬了。

    .Any().Exists() 是更安全的选择

    【讨论】:

    • new[] { "B", "AA" }.Contains("A") 将返回 false,NOT true。
    【解决方案3】:

    你的状态码也是一个集合,所以使用Contains

    var allowedStatus = new[]{ "A", "B", "C" };
    var filteredOrders = orders.Order.Where(o => allowedStatus.Contains(o.StatusCode));
    

    或在查询语法中:

    var filteredOrders = from order in orders.Order
                         where allowedStatus.Contains(order.StatusCode)
                         select order;
    

    【讨论】:

    • 我会说对于 allowedStatus 使用 HashSet 而不是数组,因为 HashSet 的 contains 方法是最快的,如果数组包含超过 1000 个项目,则会出现性能问题。 var allowedStatus = new HashSet { "A", "B", "C" };
    • @JayShah: 迟到的回答:是的,一般来说你是对的,如果你有成千上万的项目,最好首先使用HashSet<T>。但这始终不是一个好主意:如果您已经传入一个数组或列表,则需要另一个集合,因此需要更多内存。你需要填写HashSet<T>,所以更多的cpu周期。如果这不是 Linq-To-Objects 而是 Linq-To-Entities(Contains 转换为具有 limitations 的 sql-IN 子句),您可能无论如何都无法使用数千个项目。跨度>
    • @JayShah,这不会改变使用实体框架时的性能。它将被转换为 SQL "IN" 子句,并由数据库引擎执行。在这种情况下,数组的创建速度会快一些。
    【解决方案4】:

    试试Contains函数;

    确定序列是否包含指定元素。

    var allowedStatus = new[]{ "A", "B", "C" };
    var filteredOrders = orders.Order.Where(o => allowedStatus.Contains(o.StatusCode));
    

    【讨论】:

      【解决方案5】:
      var statuses = new[] { "A", "B", "C" };
      
      var filteredOrders = from order in orders.Order
                                   where statuses.Contains(order.StatusCode)
                                   select order;
      

      【讨论】:

        猜你喜欢
        • 2013-03-31
        • 1970-01-01
        • 2011-06-25
        • 1970-01-01
        • 1970-01-01
        • 2011-04-25
        • 2019-05-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多