本文介绍了如何在C#中创建合并项方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

//Items.cs
public class Items
{
    public int ItemNumber { get; set; }
    public DateTime ItemDate { get; set; }
    public List<ItemsLine> ItemsLines { get; set; } = new List<ItemsLine>();

    /// MergeItem appends the items from the sourceItem to the current item
    /// </summary>
    /// <param name="sourceItem">Item to merge from</param>
    public void MergeItem( Items sourceItem)
    {
        //IEnumerable<ItemsLine> items = new List<ItemsLine>();
        //IEnumerable<Items> items = ItemsLines.Union<item>
        
        throw new NotImplementedException();
    }
}

//ItemLine.cs
public class ItemsLine
{
    public int ItemLineId { get; set; }
    public int Quantity { get; set; }
    public double Cost { get; set; }

    // public double Total { get { return this.Cost * this.Quantity; } }

    public ItemsLine(int itemLineId, int quantity, double cost)
    {
        this.ItemLineId = itemLineId;
        this.Quantity = quantity;
        this.Cost = cost;
    }

    public ItemsLine() { }
}

//Program.cs
private static void MergeItem()
{
    var item1 = new Items();

    item1.ItemsLines.Add(new ItemsLine()
    {
        ItemLineId = 1,
        Cost = 10.33,
        Quantity = 4,
    });

    var item2 = new Items();

    item2.ItemsLines.Add(new ItemsLine()
    {
        ItemLineId = 2,
        Cost = 5.22,
        Quantity = 1,
    });

    item2.ItemsLines.Add(new ItemsLine()
    {
        ItemLineId = 3,
        Cost = 6.27,
        Quantity = 3,
    });

    item1.MergeItem(item2);
    Console.WriteLine("Grand total after merge = {0}", item1.ItemsLines.Sum(i => i.Cost * i.Quantity));
}

合并项目的规则是:

  • 传递到Merge的项目.ItemsLines中的ItemsLine实例,被添加到this.ItemsLines,或用于更新现有项目
  • ItemsLine具有一个在列表中唯一的ItemLineID
  • 如果列表中已经存在传入的ItemsLine.ItmeLineID,则应将传入项目的数量添加到现有项目中,并且应将现有成本调整为现有成本和传入成本的平均值.
  • 如果列表中不存在传入的ItemsLine.ItemLineID,则应添加ItemsLine
  • The ItemsLine instances in the .ItemsLines of the Item passed into Merge, are added to the this.ItemsLines, or used to update existing items
  • ItemsLine has an ItemLineID that is unique in the list
  • If the incoming ItemsLine.ItmeLineID already exists in the list the Quantity of the incoming item should be added to the existing item and existing Cost should be adjusted to the average of the existing and the incoming costs
  • If the incoming ItemsLine.ItemLineID doesn't exist in the list the ItemsLine should be added

我尝试使用下面的代码,但这没用

I tried using below code but that didn't work

  • IEnumerable<ItemsLine> items = new List<ItemsLine>();

IEnumerable<Items> items = ItemsLines.Union<item>()

要合并,我是否需要使用Concat ?,因此您可以组合两个实现IEnumerable或Linq join查询的集合以实现mergeitem?

To merge do i need to use Concat?, so you can combine two collections that implement IEnumerable or the Linq join query to achieve mergeritem?

推荐答案

您问如何使用"Linq连接查询"合并两个列表.从概念上讲,您提出的算法对应于两个ItemsLine列表上的完全外部联接,在ItemLineId上匹配,保留两个列表中的不匹配项,并使用问题中描述的逻辑合并匹配项:

You ask how to merge two lists using a "Linq join query". Conceptually, your proposed algorithm corresponds to a full outer join on your two ItemsLine lists, matching on the ItemLineId, preserving unmatched items from both lists as-is and merging matched items using the logic described in your question:

(来自此答案的图,由.)

不幸的是,目前LINQ中没有内置完整的外部联接.幸运的是, LINQ-完全外部联接 中有一些可行的实现.我从,并能够如下合并您的Items列表:

Unfortunately, there is no full outer join built into LINQ currently. Fortunately there are several working imlementations from LINQ - Full Outer Join. I copied Ext.FullOuterJoin<TLeft, TRight, TKey, TResult>() from this answer by NetMage, and was able to merge your Items lists as follows:

public class Items
{
    public int ItemNumber { get; set; }
    public DateTime ItemDate { get; set; }
    public List<ItemsLine> ItemsLines { get; set; } = new List<ItemsLine>();

    /// MergeItem appends the items from the sourceItem to the current item
    /// </summary>
    /// <param name="sourceItem">Item to merge from</param>
    public void MergeItem( Items sourceItem)
    {
        var mergedItems = ItemsLines.FullOuterJoin(sourceItem.ItemsLines, i => i.ItemLineId, i => i.ItemLineId, (i1, i2) =>
                                                   {
                                                       if (i1 == default)
                                                           return i2;
                                                       else if (i2 == default)
                                                           return i1;
                                                       //It's not clear from your question whether the average cost should be weighted by the quantities.
                                                       //i1.Cost = (i1.Cost + i2.Cost) / 2.0,
                                                       i1.Cost = (i1.Quantity * i1.Cost + i2.Quantity * i2.Cost) / (i1.Quantity + i2.Quantity);
                                                       i1.Quantity = i1.Quantity + i2.Quantity;
                                                       return i1;
                                                   })
            .ToList();
        ItemsLines.Clear();
        ItemsLines.AddRange(mergedItems);
    }
}

正在工作的演示小提琴此处.

Working demo fiddle here.

这篇关于如何在C#中创建合并项方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-22 21:33