从一个列表中只选择在另一个列表中出现的列表,并按第二个列表- 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 }
};
我想将data1
按Product
分组,并对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
我会采取不同的方法。
由于您希望最终结果以相同的顺序包含第二个列表中的产品,因此我将从第二个列表中获取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);