Linq Group and the sum of the problems

I have the following objects:

Subscription List Account Class:

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; } } 

subscription class with a list of options and additions:

 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; } } 

add class with a list of options:

 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; } } 

And the variation class:

 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; } } 

What I'm trying to do is group all the add-ons with a specific code and summarize the amount. For example, I tried:

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

This is one correct addition of groups, but I need a list with the addition of a subscription for each group by code and total amount per code.

For example, if a subscription has an X-number of add-ons, and the code of each add-on is 1, 2, ..., X, I want to group using add-ons by code and total number using this code. I expect the result to be something like if I have the following structure:

Pseudo-code with the current structure ( The code belongs to the Variation class, which everyone adds has):

 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 } } 

What I expect:

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

You can use this dotnetfiddle to check for dummy data.

Sorry for the long post and I will appreciate any help. Also keep in mind that my knowledge of C # and Linq is limited.

+5
source share
3 answers

If I understand correctly, the following may lead to the desired result.

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

Although I'm not quite sure that this is what you want, try this

 var codes = addOns.SelectMany(a => a.Variations).Select(v => v.Code).Distinct(); var addOnsByCode = new List<AddOn>(); //your desired result foreach (var code in codes) { var addOnsWithThisCode = addOns.Where(a => a.Variations.Any(v => v.Code == code)); addOnsByCode.Add(new AddOn{ Variations = new List<Variation> { new Variation { Code = code } }, Quantity = addOnsWithThisCode.Sum(a => a.Quantity), ID = string.Join("_", addOnsWithThisCode.Select(a => a.ID)) //not required> }); } 

Where addOns is a List<AddOn> , for example

 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" } } }, }; 
+2
source

If I understand your problem correctly, I think the following method will help. I added a method to my Subscription class to group its add-ons by its variation codes, and then summarize the number of different codes. The key to my code is using SelectMany to split one Add-On with multiple options into separate elements that connect Code and Quantity. Then you can group the broken items.

 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

+2
source

Source: https://habr.com/ru/post/1239793/


All Articles