从一个列表中只选择在另一个列表中出现的列表,并按第二个列表- linq排序

本文关键字:列表 排序 linq 第二个 一个 选择 另一个 | 更新日期: 2023-09-27 18:14:16

我有两个数组。

var data1 = new[] { 
        new { Product = "Product 1", Year = 2009, Sales = 1212 },
        new { Product = "Product 2", Year = 2009, Sales = 522 },
        new { Product = "Product 1", Year = 2010, Sales = 1337 },
        new { Product = "Product 2", Year = 2011, Sales = 711 },
        new { Product = "Product 2", Year = 2012, Sales = 2245 },
        new { Product = "Product 3", Year = 2012, Sales = 1000 }
    };
var data2 = new[] { 
        new { Product = "Product 1", Year = 2009, Sales = 1212 },
        new { Product = "Product 1", Year = 2010, Sales = 1337 },
        new { Product = "Product 2", Year = 2011, Sales = 711 },
        new { Product = "Product 2", Year = 2012, Sales = 2245 }
    };

我想将data1Product分组,并对data2中存在的产物按Sales分组求和,并按data2中的顺序排序。请注意,即使产品出现在data2中,该产品在data1中出现的所有年份也不会出现在data2中(例如:{ Product = "Product 2", Year = 2009, Sales = 522 }),因此分组和求和必须在data1上进行。

只要把下面的分组和求和就可以了。

data1.GroupBy(x=>x.Product)
.Select(x=>new {Product=x.Key,Total= x.Sum(s=>s.Sales)})

但是我如何确保我只选择data2中的产品并通过Product订购结果,如data2

从一个列表中只选择在另一个列表中出现的列表,并按第二个列表- linq排序

我会采取不同的方法。

由于您希望最终结果以相同的顺序包含第二个列表中的产品,因此我将从第二个列表中获取Distinct产品开始。

虽然没有在文档中明确说明,但是Distinct方法(类似于GroupBy)按照源中唯一元素第一次出现的顺序产生不同的元素,因此Distinct的结果将是最终结果的正确顺序的乘积。

然后我将使用GroupJoin将其与第一个列表关联起来,最终得到一个相当有效的查询:

var result = data2.Select(item => item.Product).Distinct()
    .GroupJoin(data1, product => product, item => item.Product, (product, group) =>
        new { Product = product, Sales = group.Sum(item => item.Sales) })
    .ToList();

您需要做两件事:首先,从data2中选择可用的产品。为此,您可以使用Select的重载,它也给出了匹配元素的索引。

其次,根据data2中的产品筛选data1,然后执行分组。作为最后一步,添加一个新的属性CorrespondingIndex,它与data2中产品的索引相匹配。此索引可用于根据data2中的产品排序对data1列表进行排序。

  var productsWithIndex = data2
    .Select(x => x.Product)
    .Distinct()
    .Select((p, idx) => new {Product = p, Index = idx});
  var filteredProducts = data1
    .Where(x => productsWithIndex.Select(p => p.Product).Contains(x.Product))
    .GroupBy(x => x.Product)
    .Select(x => new
    {
      Product = x.Key,
      Total = x.Sum(s => s.Sales),
      CorrespondingIndex = productsWithIndex.Single(p => p.Product == x.Key).Index
    })
    .OrderBy(x => x.CorrespondingIndex);

也许您甚至不需要像user1384848那样讲那么多细节。您可以使用更简单的代码:

var result =
                data1.Where(e => data2.Any(x => x.Product == e.Product))
                    .GroupBy(arg => arg.Product,
                        (name, products) => new {Product = name, Total = products.Sum(e => e.Sales)})
                    .OrderBy(d => d.Product);