You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在C#中实现符合指定规则的MergeItem合并方法?

搞定Items类的MergeItem方法实现!

嘿,我来帮你解决这个合并逻辑的问题~你的思路方向是对的,Linq确实能帮我们高效实现需求,但需要结合业务规则来处理「更新现有项、添加新项」的逻辑,而不是单纯用Union或者Concat。我们直接来看符合要求的实现:

完整的MergeItem方法实现

public void MergeItem(Items sourceItem)
{
    if (sourceItem?.ItemsLines == null)
        return; // 空参数直接返回,避免踩空引用的坑

    foreach (var sourceLine in sourceItem.ItemsLines)
    {
        // 找当前集合里有没有相同ItemLineId的项
        var existingLine = ItemsLines.FirstOrDefault(line => line.ItemLineId == sourceLine.ItemLineId);
        
        if (existingLine != null)
        {
            // 按规则3合并:累加数量,算加权平均成本(比简单平均更合理哦)
            var totalQuantity = existingLine.Quantity + sourceLine.Quantity;
            var totalCostAmount = existingLine.Cost * existingLine.Quantity + sourceLine.Cost * sourceLine.Quantity;
            existingLine.Quantity = totalQuantity;
            existingLine.Cost = totalCostAmount / totalQuantity;
        }
        else
        {
            // 规则4:没找到就加新项,建议创建新实例避免外部修改影响原集合
            ItemsLines.Add(new ItemsLine(sourceLine.ItemLineId, sourceLine.Quantity, sourceLine.Cost));
        }
    }
}

为啥这个实现符合你的规则?

我们逐条对应你给的合并规则:

  • 规则1:遍历传入的sourceItem的每一行ItemsLine,逐个处理更新或添加
  • 规则2:通过FirstOrDefault基于ItemLineId查找,保证了ID唯一性的处理逻辑
  • 规则3:这里用了加权平均成本(不是简单把两个成本相加除以2),比如原有4个10.33的,新增1个5.22的,总成本是410.33+15.22,平均成本按总金额除以总数量算,更贴合实际业务
  • 规则4:找不到匹配ID的项时,直接添加新的ItemsLine

说说你之前尝试的代码问题

你之前写的这段:

IEnumerable<ItemsLine> items = new List<ItemsLine>();
IEnumerable<Items> items = ItemsLines.Union<item>()

有几个明显的问题:

  1. 重复定义了变量items,而且类型还不一致(一会是ItemsLine集合,一会是Items集合)
  2. Union默认是按对象引用相等来合并的,不会自动识别ItemLineId的匹配,更没法实现「合并数量、平均成本」的业务逻辑
  3. 泛型参数Union<item>写错了,应该是Union<ItemsLine>,但就算改对了,也只是简单合并两个集合,完全不符合你的规则要求

可选的Linq简洁写法(适合不需要保留原实例的场景)

如果你偏爱用Linq写更简洁的代码,也可以用GroupBy来合并两个集合,然后重新构建ItemsLines:

public void MergeItem(Items sourceItem)
{
    if (sourceItem?.ItemsLines == null)
        return;

    // 合并两个集合,按ItemLineId分组计算
    var mergedLines = ItemsLines.Concat(sourceItem.ItemsLines)
                                .GroupBy(line => line.ItemLineId)
                                .Select(group => 
                                {
                                    var totalQty = group.Sum(line => line.Quantity);
                                    var totalCost = group.Sum(line => line.Cost * line.Quantity);
                                    return new ItemsLine(group.Key, totalQty, totalCost / totalQty);
                                });

    // 替换原集合(如果允许替换的话,也可以先清空原集合再AddRange)
    ItemsLines = mergedLines.ToList();
}

这种写法代码更短,但要注意:它会重新创建所有ItemsLine实例,如果原集合里的实例有其他关联逻辑(比如绑定到UI),可能需要谨慎使用哦。


内容的提问来源于stack exchange,提问作者h d

火山引擎 最新活动