基于数量字段生成多对象:能否通过LINQ实现优雅写法?
用LINQ优雅拆分ERP合并的商品行项
嘿,这个需求我之前做ERP集成的时候刚好碰到过!把合并的同款商品行项拆成单个实例,用LINQ确实能写出比传统循环更优雅的代码,完全不用纠结手动遍历的细节。
先明确下场景:
ERP系统会将同款商品的行项合并为单条记录(例如数量为3),需拆分为每个单位对应一个对象(此例为3个),还要处理数量为负数的情况(所以用
Math.Abs取绝对值)
先假设我们的商品行项类是这样的
public class ProductLineItem { public string ProductId { get; set; } public string ProductName { get; set; } public int Quantity { get; set; } // 其他业务属性... }
最简洁的LINQ实现方案
核心思路是用SelectMany扁平化拆分结果,配合Enumerable.Range生成对应数量的序列:
var mergedItems = new List<ProductLineItem> { new ProductLineItem { ProductId = "P001", ProductName = "笔记本", Quantity = 3 }, new ProductLineItem { ProductId = "P002", ProductName = "钢笔", Quantity = -2 } // 负数代表退货/出库的情况 }; var splitItems = mergedItems // 先过滤掉数量为0的无效行项(可选) .Where(item => item.Quantity != 0) // 把每个合并项拆成N个单量项,然后扁平化列表 .SelectMany(item => Enumerable.Range(1, Math.Abs(item.Quantity)) .Select(_ => new ProductLineItem { ProductId = item.ProductId, ProductName = item.ProductName, Quantity = Math.Sign(item.Quantity), // 保留原数量的正负标识 // 复制其他所有属性 }));
优化:抽离对象创建逻辑
如果商品属性很多,重复复制代码太麻烦,可以把创建单量项的逻辑抽成单独方法,让代码更干净:
// 抽离的工具方法 private static ProductLineItem CreateSingleQuantityItem(ProductLineItem originalItem) { return new ProductLineItem { ProductId = originalItem.ProductId, ProductName = originalItem.ProductName, Quantity = Math.Sign(originalItem.Quantity), // 这里复制其他属性,或者用AutoMapper之类的工具简化 // 比如:Mapper.Map<ProductLineItem>(originalItem) 然后修改Quantity }; } // 调用时的LINQ代码 var splitItems = mergedItems .Where(item => item.Quantity != 0) .SelectMany(item => Enumerable.Range(1, Math.Abs(item.Quantity)) .Select(_ => CreateSingleQuantityItem(item)));
对比传统循环写法
原来的循环写法虽然可行,但代码更偏向命令式,需要手动处理循环计数:
var splitItems = new List<ProductLineItem>(); foreach (var item in mergedItems) { var total = Math.Abs(item.Quantity); var sign = Math.Sign(item.Quantity); for (int i = 0; i < total; i++) { splitItems.Add(new ProductLineItem { ProductId = item.ProductId, ProductName = item.ProductName, Quantity = sign }); } }
LINQ版本的优势在于声明式编程:你只需要告诉程序“我要把每个合并项拆成N个单量项”,不用关心循环的细节,代码可读性更高,也更容易和其他LINQ操作(比如排序、过滤)组合起来。
注意点
- 如果商品类有大量属性,手动复制容易遗漏,可以用AutoMapper、Mapster这类对象映射工具来简化对象复制
- 记得处理数量为0的情况,避免生成无效的空行项
内容的提问来源于stack exchange,提问作者Lock
相关产品推荐
相关产品推荐

