You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于数量字段生成多对象:能否通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:42:43