使用Linq整合List <t>?

时间:2016-04-27 15:14:28

标签: c# linq lambda

我只是想知道是否有办法用linq整合订单对象列表?我的情况如下,我为了这个问题而缩减了。

public class Order
{
    public string Guid { get; set; }
    public string Parent { get; set; }
    public string ProductID { get; set; }
    public string Description { get; set; }
    public double Quantity { get; set; }
    public double Total { get; set; }
}

这将成为基于以上内容的List,如下所示:

GUID       PARENT       ID         Desc          Qty           Total
====================================================================
aaa                     120        Burger         1            2.50
bbb        aaa          121        + Bacon        1            0.50
ccc                     123        Fries          1            1.50
ddd                     120        Burger         1            2.50
eee        ddd          124        + Cheese       1            0.30
fff                     123        Fries          1            1.50

我想在这个例子中做的是最终得到以下

GUID       PARENT       ID         Desc          Qty           Total
====================================================================
aaa                     120        Burger         1            2.50
bbb        aaa          121        + Bacon        1            0.50
ccc                     123        Fries          2            3.00
ddd                     120        Burger         1            2.50
eee        ddd          124        + Cheese       1            0.30

如果该商品具有子商品,我不会尝试合并,并且基本上总和为其他所有商品的总数和数量。

我当时的想法是创建一个单独的列表,其中只列出没有孩子的产品,并与有孩子的产品进行精心合并。

我可以这样做,但我想知道是否有更清洁的方法,任何输入都会有很大的影响

3 个答案:

答案 0 :(得分:3)

这应该保持与孩子的订单分开,并且只合并独立订单:

var orders = originalOrders.GroupBy(_ => _.parent ? _.parent : _.guid);
var consolidated = orders
    .Where(grp => grp.Count() == 1) // only orders with no children
    .SelectMany(grp => grp)
    .GroupBy(_ => _.ID)
    .Select(grp => grp.Aggregate((a,b) => new order
        {
            guid = a.guid,
            parent = a.parent,
            ProductID = a.ProductID,
            Description = a.Description,
            Quantity = a.Quantity + b.Quantity,
            Total = a.Total + b.Total
        }
));

var allOrders = orders
    .Where(grp => grp.Count() > 1)
    .SelectMany(grp => grp)
    .Concat(consolidated);

答案 1 :(得分:2)

如果您想一次性完成此操作,关键是要计算要分组的内容。 由于我们不想将带有孩子的物品分组,因此我们需要为这些物品分组。如果我们拿两个汉堡行,那么唯一不同的是Guid,所以这需要在我们的分组中。如果项目没有子行,我们应该对它们进行分组。 因此,如果项目具有子项,我们计算成为Guid的组子句,如果项目没有子项,则计算为空字符串。 然后,ProductID也需要进行分组,因为这是我们想要对没有子项的项目进行分组。

var lst = orders.GroupBy(x => new
{
    x.ProductID,
    GuidIfHaveChildren = (orders.Any(x2 => x2.Parent == x.Guid) ? x.Guid : ""),
    x.parent
}).Select(x => new
 {
     Guid = x.First().Guid,
     Parent = x.First().Parent,
     Id = x.Key.ProductID,
     Desc = x.First().Description,
     Qty = x.Sum(p => p.Quantity),
     Total = x.Sum(p => p.Total)
 });

答案 2 :(得分:1)

from o in orders
group o by o.ID into g
from gg in g select new Order
{
        guid = gg.guid, parent = gg.parent, ProductId = gg.ProductId, Description = gg.Description,
        Quantity = orders.Any(od=> od.parent != null || od.parent == gg.guid) 
                        ? gg.Quantity : g.Sum(ggg=>ggg.Quantity),
        Total = orders.Any(od=> od.parent != null || od.parent == gg.guid) 
                        ? gg.Total : g.Sum(ggg=>ggg.Total)
}

这可能存在一些性能问题,但这应该可以帮助您入门。