3 nested groups with linq

I'm trying to get the 4th list of list of lists List<List<List<List<int>>>>

. From my Xml that looks like

    <Claim key="1" carrier="carA" zip="34343" pages="1"/>
    <Claim key="2" carrier="carA" zip="34343" pages="2"/>
    <Claim key="3" carrier="carB" zip="10505" pages="2"/>
    <Claim key="4" carrier="carB" zip="10505" pages="4"/> 
    <Claim key="5" carrier="carB" zip="10505" pages="4"/>


the output structure should look like





the goal is to sort my XML based on node attributes first by number of pages, then by zip, then by carrier. Then I will need to iterate over the list of results and process each request in a specific order. I am having problems getting the syntax for 3 nested groups. I have made sure that two nested groups can help me get the third.

here is my code.

var query = from claim in root.Elements("Claim")
                        group claim by claim.Attributes("Pages").First().Value into pageGroups
                        from zipGroups in
                            (from claim in pageGroups
                             group claim by int.Parse(claim.Attributes("CarrierZip").First().Value))
                        group zipGroups by pageGroups.Key;



source to share

2 answers

If nothing else I believe this code answers your question. Having to handle four nested lists is pretty tricky, and if you can refactor your solution to something simpler, you will likely find your code easier to maintain.

var xml = @"<root>  
  <Claim key=""1"" carrier=""carA"" zip=""34343"" pages=""1""/> 
  <Claim key=""2"" carrier=""carA"" zip=""34343"" pages=""2""/> 
  <Claim key=""3"" carrier=""carB"" zip=""10505"" pages=""2""/> 
  <Claim key=""4"" carrier=""carB"" zip=""10505"" pages=""4""/>  
  <Claim key=""5"" carrier=""carB"" zip=""10505"" pages=""4""/>

var xElement = XElement.Parse(xml);

var claims = xElement
    x => new {
      Key = (Int32) x.Attribute("key"),
      Carrier = (String) x.Attribute("carrier"),
      Zip = (Int32) x.Attribute("zip"),
      Pages = (Int32) x.Attribute("pages")

var lists = claims
  .OrderBy(claim => claim.Pages)
  .GroupBy(claim => claim.Pages)
  .Select(pagesGroup => pagesGroup
    .OrderBy(claim => claim.Zip)
    .GroupBy(claim => claim.Zip)
    .Select(zipGroup => zipGroup
      .OrderBy(claim => claim.Carrier)
      .GroupBy(claim => claim.Carrier)
      .Select(carrierGroup => carrierGroup
        .OrderBy(claim => claim.Key)
        .Select(claim => claim.Key)




I'm not sure how to do this with XML, but if you have already transferred the claim to an array of some type Claim

(for example, in the code claims

has a type Claim[]

) and type Claim

a property or field called Key

, Carrier

, Zip

and Pages

then it should work.

var dic = (from claim in claims
           group claim by claim.Pages into pageGroup
           select new {
               Page = pageGroup.Key,
               Entries =
                   (from zentry in pageGroup
                    group zentry by zentry.Zip into zipGroup
                    select new {
                        Zip = zipGroup.Key,
                        Entries =
                            (from centry in zipGroup
                             group centry by centry.Carrier into carrierGroup
                             select new { Carrier = carrierGroup.Key, Entries = carrierGroup.AsEnumerable() })
                            .ToDictionary(ent => ent.Carrier, ent => ent.Entries)
                    }).ToDictionary(ent => ent.Zip, ent => ent.Entries)
           }).ToDictionary(ent => ent.Page, ent => ent.Entries);


It's not very clean, but it works. You can select a claim with this page, mail and media, for example:

var myclaim = dic[4][34343]["carB"];


I decided to give you a way to translate to Dictionary<TKey, TValue>

instead List<T>

because translation to List

loses the key, so the only way to get the key (page, zip or carrier) would be to traverse the list down, which can get ugly and complicated. Sorry if the dictionary won't work for you.



All Articles