首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Linq - SelectMany混淆

Linq - SelectMany混淆
EN

Stack Overflow用户
提问于 2011-02-16 23:30:10
回答 3查看 88.1K关注 0票数 83

根据我对SelectMany文档的理解,可以使用它来生成一个1-多关系的(扁平的)序列。

我有以下课程

代码语言:javascript
复制
  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; }
  }

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

代码语言:javascript
复制
  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);

这给了我需要的东西。

代码语言:javascript
复制
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查询吗?

EN

回答 3

Stack Overflow用户

发布于 2011-02-16 23:38:00

SelectMany()的工作方式与Select类似,但有一个额外的功能,即使选定的集合变平。只要你想要投影子集合的元素,而不关心子集合的包含元素,就应该使用它。

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

代码语言:javascript
复制
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将如下所示:

代码语言:javascript
复制
var customerOrders = Customers
                        .SelectMany(c=>c.Orders)
                        .Select(o=> new { CustomerId = o.Customer.Id, 
                                           OrderDescription = o.Description });

..。这将产生相同的结果,而不需要订单的平面集合。SelectMany获取每个客户的Orders集合,并遍历该集合以从IEnumerable<Customer>生成IEnumerable<Order>

票数 27
EN

Stack Overflow用户

发布于 2013-02-16 12:06:56

虽然这是一个老问题,但我想我会改进一下优秀的答案:

SelectMany为控制列表的每个元素返回一个列表(可能为空)。这些结果列表中的每个元素都被枚举到表达式的输出序列中,因此被连接到结果中。因此,a‘list -> b’list[] ->串联-> b‘列表。

代码语言:javascript
复制
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using System.Diagnostics;
namespace Nop.Plugin.Misc.WebServices.Test
{
    [TestClass]
    public class TestBase
    {
        [TestMethod]
        public void TestMethod1()
        {  //See result in TestExplorer - test output 
            var a = new int[]{7,8};
            var b = new int[]
                    {12,23,343,6464,232,75676,213,1232,544,86,97867,43};
            Func<int, int, bool> numberHasDigit = 
                    (number
                     , digit) => 
                         ( number.ToString().Contains(digit.ToString()) );

            Debug.WriteLine("Unfiltered: All elements of 'b' for each element of 'a'");
            foreach(var l in a.SelectMany(aa => b))
                Debug.WriteLine(l);
            Debug.WriteLine(string.Empty);
            Debug.WriteLine("Filtered:" +  
            "All elements of 'b' for each element of 'a' filtered by the 'a' element");
            foreach(var l in a.SelectMany(aa => b.Where(bb => numberHasDigit(bb, aa))))
                Debug.WriteLine(l);
        }
    }
}
票数 5
EN

Stack Overflow用户

发布于 2017-09-16 17:26:14

下面是使用SelectMany的另一种选择

代码语言:javascript
复制
var customerOrders = customers.SelectMany(
  c => orders.Where(o => o.CustomerId == c.Id)
    .Select(p => new {CustomerId = c.Id, OrderDescription = p.Description}));

如果使用Entity Framework或LINQ to Sql,并且实体之间存在关联(关系),则可以执行以下操作:

代码语言:javascript
复制
var customerOrders = customers.SelectMany(
  c => c.orders
   .Select(p => new {CustomerId = c.Id, OrderDescription = p.Description}));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5018361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档