streamdown streamdown - 12 days ago 6
C# Question

Merge two collections and sum the fields for duplicate items

I have a two collections:

public interface ISomeNeededInterface
{
string Name { get; set; }
Guid Guid { get; set; }
}

public class Order : ISomeNeededInterface
{
public string Name { get; set; }
public Guid Guid { get; set; }
}

public class SalesOrder
{
public string Name { get { return Item.Name;} }
public double Price { get; set; }
public int Quantity { get; set; }
private ISomeNeededInterface Item { get; private set; }

public SalesOrder(ISomeNeededInterface _item)
{
Item = _item;
Price = _item.Pricce;
Quantity = _item.Quantity;
}
}

List<SalesOrder> Orders1 = new List<SalesOrder>()
{
new SalesOrder(new Order {"Ballon1", Guid.NewGuid();}, 2.54, 1),
new SalesOrder(new Order {"Ballon2", Guid.NewGuid();}, 2.54, 1),
};

List<SalesOrder> Orders2 = new List<SalesOrder>()
{
new SalesOrder(new Order {"Ballon1", Guid.NewGuid();}, 2.54, 2),
new SalesOrder(new Order {"Ball", Guid.NewGuid();}, 4.52, 1)
};


How to merge two collections into one, as well as to merge those elements that have coincided "Name" fields? At the same time, for the elements, merged names must sum of the field "Quantity". At the end must be

List<SalesOrder> SummOrders = {"Ballon1", 2.54, 3, SOME_Item; "Ballon2", 2.54, 1, SOME_Item ; "Ball", 4.52, 1, SOME_Item }


Edited: need clarify for simple question?? Ok, there is more real "edited"

Answer

Use Concat, GroupBy and Sum:

List<SalesOrder> merged = Order1.Concat(Orders2)
    .GroupBy(so => so.Name)
    .Select(g => new SalesOrder(g.Key, g.First().Price, g.Sum(so => so.Quantity)))
    .ToList();

Consider that the Name could be equal but it has a different Price, so it's actually a different product. Then you could group by an anonymous type containing both properties (ideally you use a unique identifier):

List<SalesOrder> merged = Order1.Concat(Orders2)
    .GroupBy(so => new { so.Name, so.Price })
    .Select(g => new SalesOrder(g.Key.Name, g.Key.Price, g.Sum(so => so.Quantity)))
    .ToList();