Linq-有没有SelectMany的方法?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (54)

根据我从SelectMany的文档中了解到的情况,人们可以使用它生成一个1-多关系的(扁平的)序列。

我有以下课程

  public class Customer
  {
    public int Id { get; set; }
    public string Name { get; set; }
  }

  class Order
  {
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public string Description { get; set; }
  }

然后,我尝试使用查询表达式语法,如下所示

  var customers = new Customer[]
  {
    new Customer() { Id=1, Name ="A"},
    new Customer() { Id=2, Name ="B"},
    new Customer() { Id=3, Name ="C"}
  };

  var orders = new Order[]
  {
    new Order { Id=1, CustomerId=1, Description="Order 1"},
    new Order { Id=2, CustomerId=1, Description="Order 2"},
    new Order { Id=3, CustomerId=1, Description="Order 3"},
    new Order { Id=4, CustomerId=1, Description="Order 4"},
    new Order { Id=5, CustomerId=2, Description="Order 5"},
    new Order { Id=6, CustomerId=2, Description="Order 6"},
    new Order { Id=7, CustomerId=3, Description="Order 7"},
    new Order { Id=8, CustomerId=3, Description="Order 8"},
    new Order { Id=9, CustomerId=3, Description="Order 9"}
  };

  var customerOrders = from c in customers
                       from o in orders
                       where o.CustomerId == c.Id
                       select new 
                              { 
                                 CustomerId = c.Id
                                 , OrderDescription = o.Description 
                              };

  foreach (var item in customerOrders)
    Console.WriteLine(item.CustomerId + ": " + item.OrderDescription);

这给了我所需要的。

1: Order 1
1: Order 2
1: Order 3
1: Order 4
2: Order 5
2: Order 6
3: Order 7
3: Order 8
3: Order 9

如果不使用查询表达式语法,我假设这会转换为使用SelectMany方法?

不管怎样,我都想用SelectMany来说服自己。因此,即使考虑到这两个类和模拟数据,即使我的上面的查询没有转换到SelectMany,有人能为我提供一个使用SelectMany的Linq查询吗?

提问于
用户回答回答于

下面是使用SelectMany:

        var customerOrders2 = customers.SelectMany(
            c => orders.Where(o => o.CustomerId == c.Id),
            (c, o) => new { CustomerId = c.Id, OrderDescription = o.Description });

第一个参数将每个客户映射到一个订单集合(与您已经拥有的“WHERE”子句完全相反)。

第二个参数将每个匹配的对{(C1,o1),(C1,O2)...(c3,o9)}转换为一个新类型,这与我的示例相同。

因此:

  • arg 1将基集合中的每个元素映射到另一个集合。
  • arg 2(可选)将每对转换为新类型。

得到的集合与您在最初的示例中所期望的一样是平坦的。

如果您省略第二个参数,那么您将得到所有订单的集合。

用户回答回答于

SelectMany()的工作方式类似SelectSelect,但它具有将所选集合扁平化的额外功能。当您想要子集合元素的投影时,应该使用它,而不关心子集合的包含元素。

例如,假设您的域如下所示:

public class Customer
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Order> Orders { get; set; }
  }

  class Order
  {
    public int Id { get; set; }
    public Customer Customer { get; set; }
    public string Description { get; set; }
  }

为了得到您想要的列表,Linq应该如下所示:

var customerOrders = Customers
                        .SelectMany(c=>c.Orders)
                        .Select(o=> new { CustomerId = o.Customer.Id, 
                                           OrderDescription = o.Description });

这将产生同样的结果,而不需要统一的订单收集.。SelectMany接受每个客户的订单集合,并遍历该集合以生成一个IEnumerable<Order>IEnumerable<Customer>...

所属标签

可能回答问题的人

  • 人生的旅途

    10 粉丝484 提问5 回答
  • 无聊至极

    4 粉丝504 提问5 回答
  • 骑牛看晨曦

    5 粉丝522 提问4 回答
  • 嗨喽你好

    7 粉丝480 提问4 回答

扫码关注云+社区

领取腾讯云代金券