如何用LINQ将ProductStock按ComboProduct组合生成Result列表?
用LINQ实现产品组合库存计算需求
更新说明
为清晰起见,将类名修改为ComboProduct和Product
public class Product { public string Name {get; set;} } public class ComboProduct { public int Id; public List<Product> ProductList {get; set;} } public class ProductStock { public Product Product {get; set;} public int Quantity {get; set;} public double Price {get; set;} } public class Result { public int ComboProductId {get; set;} public int Quantity {get; set;} public double Price {get; set;} }
示例数据
- Product:A、B、C、D、E……
- ComboProduct:
{1, [A , B, C]}
ProductStock 数据
| Product | Quantity | Price |
|---|---|---|
| A | 5 | 10 |
| A | 60 | 15 |
| A | 55 | 20 |
| B | 25 | 30 |
| B | 9 | 35 |
| C | 40 | 100 |
| C | 68 | 70 |
| C | 27 | 90 |
需求
使用LINQ将ProductStock按上述ComboProduct的产品组合生成Result列表,要求:
- 每个
Result的Price为组合内各ProductStock的Price之和 Quantity为组合内各ProductStock的Quantity的最小值- 包含对应的
ComboProductId
用户已用C#算法实现,现寻求LINQ方案。
预期结果示例
| 组合 | ComboProductId | Price | Quantity |
|---|---|---|---|
| (A1,B1,C1) | 1 | 140 | 5 |
| (A2,B1,C1) | 1 | 145 | 25 |
| (A2,B2,C1) | 1 | 150 | 9 |
| …… | …… | …… | …… |
| (A3,B1,C2) | 1 | 120 | 25 |
| …… | …… | …… | …… |
LINQ实现方案
核心思路是先按产品名称分组库存项,生成组合内各产品库存的笛卡尔积,再计算每个组合的总价与最小数量。
单个组合的实现
// 假设已有目标组合与库存数据 ComboProduct targetCombo = new ComboProduct { Id = 1, ProductList = new List<Product> { new Product { Name = "A" }, new Product { Name = "B" }, new Product { Name = "C" } } }; List<ProductStock> productStocks = new List<ProductStock> { new ProductStock { Product = new Product { Name = "A" }, Quantity = 5, Price = 10 }, new ProductStock { Product = new Product { Name = "A" }, Quantity = 60, Price = 15 }, new ProductStock { Product = new Product { Name = "A" }, Quantity = 55, Price = 20 }, new ProductStock { Product = new Product { Name = "B" }, Quantity = 25, Price = 30 }, new ProductStock { Product = new Product { Name = "B" }, Quantity = 9, Price = 35 }, new ProductStock { Product = new Product { Name = "C" }, Quantity = 40, Price = 100 }, new ProductStock { Product = new Product { Name = "C" }, Quantity = 68, Price = 70 }, new ProductStock { Product = new Product { Name = "C" }, Quantity = 27, Price = 90 } }; // 按产品名称分组库存项 var groupedStocks = productStocks.GroupBy(ps => ps.Product.Name) .ToDictionary(g => g.Key, g => g.ToList()); // 生成组合内各产品库存的笛卡尔积 var cartesianProduct = targetCombo.ProductList .Select(p => groupedStocks[p.Name]) .Aggregate( Enumerable.Repeat(new List<ProductStock>(), 1), (currentCombos, nextStocks) => from combo in currentCombos from stock in nextStocks select combo.Concat(new[] { stock }).ToList() ); // 转换为Result列表 var results = cartesianProduct .Select(combo => new Result { ComboProductId = targetCombo.Id, Quantity = combo.Min(ps => ps.Quantity), Price = combo.Sum(ps => ps.Price) }) .ToList();
多个组合的批量处理
如果需要同时处理多个ComboProduct,可以在外层增加遍历逻辑:
List<ComboProduct> allCombos = new List<ComboProduct> { targetCombo /* 其他组合 */ }; var allResults = allCombos.SelectMany(combo => { var grouped = productStocks.GroupBy(ps => ps.Product.Name) .ToDictionary(g => g.Key, g => g.ToList()); var productGroups = combo.ProductList.Select(p => grouped[p.Name]); var cartesian = productGroups.Aggregate( Enumerable.Repeat(new List<ProductStock>(), 1), (curr, next) => curr.SelectMany(c => next.Select(n => c.Concat(new[] {n}).ToList())) ); return cartesian.Select(c => new Result { ComboProductId = combo.Id, Quantity = c.Min(ps => ps.Quantity), Price = c.Sum(ps => ps.Price) }); }).ToList();
内容的提问来源于stack exchange,提问作者Khanh Nguyen Van
相关产品推荐
相关产品推荐

