I have the following entities:
An account class with a list of subscriptions:
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; }
}
the subscription class with a list of variations and add ons:
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; }
}
the add on class with a list of variations:
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 to group all add ons with specific Code and sum the quantity. For example I tried:
var groupAddOnsByCode = acc.Subscriptions.Select(s => s.AddOns.GroupBy(a => a.Variations.Select(v => v.Code).FirstOrDefault())).ToList();
This one correct groups add ons but I want a list with with add ons per subscription group by code and total quantity per code.
For example if a Subscription has X number of add ons and the Code of each add on is 1, 2, ..., X, I want to group by the add ons by Code and total Quantity with this Code. I expect the result will be something like if I have the following structure:
A pseudo-code with current structure(Code refers to Variation Class that each add on 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 test dummy data.
Sorry for the long post and I will appreciate any help. Also keep in mind my c# and Linq knowledge is limited.
If I understand correctly, the following might produce 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 => e.v.Code, (key, elements) => new
{
Code = key,
Quantity = elements.Sum(e => e.a.Quantity)
}).ToList()
}).ToList();
Though I'm not completely sure 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" }
}
},
};
If I understood your problem correctly I think that the following method will help. I added a method within your Subscription
class to group its add-ons by its Variation Codes and then sum the quantities of various codes. The key to my code is using SelectMany
to break a single Add-On with multiple variants into separate elements that pair Code and Quantity. Then you can group the broken-up elements.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With