Linq Group by和sum问题

时间:2016-01-04 14:04:40

标签: c# linq

我有以下实体:

包含订阅列表的帐户类:

public class Account
{
    /// <summary>
    /// Account ID
    /// </summary>
    public string ID { get; set; }

    /// <summary>
    /// A List with all subscriptions
    /// </summary>
    public IEnumerable<Subscription> Subscriptions { get; set; }
}

包含变体列表和附加内容的订阅类:

public class Subscription
{
    /// <summary>
    /// Subscription ID
    /// </summary>
    public string ID { get; set; }

    /// <summary>
    /// Quantity of the subscription.
    /// </summary>
    public int Quantity { get; set; }

    /// <summary>
    /// A list with all subscription add ons
    /// </summary>
    public IEnumerable<AddOn> AddOns { get; set; }

    /// <summary>
    /// A List with all subscription variations
    /// </summary>
    public IEnumerable<Variation> Variations { get; set; }
}

带有变体列表的类添加:

public class AddOn
{
    /// <summary>
    /// Gets or Sets add on id
    /// </summary>
    public string ID { get; set; }

    /// <summary>
    /// Quantity of the add on.
    /// </summary>
    public int Quantity { get; set; }

    /// <summary>
    /// A List with all add on variations
    /// </summary>
    public IEnumerable<Variation> Variations { get; set; }

}

变异类:

public class Variation
{
    /// <summary>
    /// Variation ID
    /// </summary>
    public string ID { get; set; }

    /// <summary>
    /// offerUri
    /// </summary>
    public string Code { get; set; }

    /// <summary>
    /// Variation Value
    /// </summary>
    public string Value { get; set; }

    /// <summary>
    /// Variation Name
    /// </summary>
    public string Name { get; set; }

}

我要做的是将所有添加内容与特定代码分组并对数量求和。例如,我试过:

var groupAddOnsByCode = acc.Subscriptions.Select(s => s.AddOns.GroupBy(a => a.Variations.Select(v => v.Code).FirstOrDefault())).ToList();

这是一个正确的群组添加,但我想要一个列表,每个订阅组按代码和每个代码的总数量添加。

例如,如果订阅具有X个附加组件且每个添加的代码为1,2,...,X,我希望按代码添加分组和使用此代码的总数量。我希望结果会像我有以下结构:

具有当前结构的伪代码(代码指的是每个添加的变体类):

Subscription {
 //a list with X number of add ons
 AddOn1 = { Variation = { Code = 1 }, Quantity = 2 },
 AddOn2 = { Variation = { Code = 2 }, Quantity = 3 },
 ...
 AddOnX = { Variation = { Code = X }, Quantity = 4 }
}

我的期望:

Subscription {
    AddOn1 { Variation = { Code = 1 }, Quantity = totalAmountOfQuantityForAddOnsWithCode = 1 },
    ...
    AddOnX { Variation = { Code = X }, Quantity = totalAmountOfQuantityForAddOnsWithCode = X },
}

您可以使用此dotnetfiddle来测试虚拟数据。

很抱歉这篇长篇文章,我将不胜感激任何帮助。还要记住我的c#和Linq知识是有限的。

3 个答案:

答案 0 :(得分:5)

如果我理解正确,以下可能会产生所需的结果

var result = acc.Subscriptions.Select(s => new
{
    Subscription = s,
    AddOns = s.AddOns.SelectMany(a => a.Variations, (a, v) => new { a, v })
        .GroupBy(e => e.v.Code, (key, elements) => new 
        { 
            Code = key,
            Quantity = elements.Sum(e => e.a.Quantity)
        }).ToList()
}).ToList();

答案 1 :(得分:2)

虽然我不完全确定这是你想要的,但试试这个

addOns

其中List<AddOn>var addOns = new List<AddOn> { new AddOn { ID = "1", Quantity = 5, Variations = new List<Variation> { new Variation { Code = "A" }, new Variation { Code = "B" } } }, new AddOn { ID = "2", Quantity = 7, Variations = new List<Variation> { new Variation { Code = "B" }, new Variation { Code = "C" } } }, new AddOn { ID = "3", Quantity = 9, Variations = new List<Variation> { new Variation { Code = "D" }, new Variation { Code = "A" } } }, }; ,例如

{{1}}

答案 2 :(得分:2)

如果我理解你的问题,我认为以下方法会有所帮助。我在Subscription类中添加了一个方法,通过其变体代码对其附加组件进行分组,然后对各种代码的数量求和。我的代码的关键是使用SelectMany将具有多个变体的单个附加组件分解为将代码和数量配对的单独元素。然后你可以对破碎的元素进行分组。

public Dictionary<string, int> GetAddonGroups()
{
    //spreading out each Add-on into multiple elements, each with a Code and quantity
    var addOnVariationsWithQuantity = this.AddOns
        .SelectMany(ad =>  ad.Variations
                    .Select(v => new {Code = v.Code, Quantity = ad.Quantity}));

    //group by Code and Sum the quantity
    var addOnGroups = addOnVariationsWithQuantity
                        .GroupBy(v => v.Code)
                        .ToDictionary(grp => grp.Key, 
                                      grp => grp.Sum( el => el.Quantity));
    return addOnGroups;
}

Forked Fiddle