【问题标题】:3 nested groups with linq3 个带有 linq 的嵌套组
【发布时间】:2012-03-20 19:22:33
【问题描述】:

我正在尝试获取 4 个列表深度列表集合,List<List<List<List<int>>>>。从我的 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"/>
</root>

输出的结构应该是这样的

-all
   -1
       -34343
           -carA
                   -1

   -2
       -34343
           -carA
                   -2

       -10505
               -carB
                   -3
   -4
       -10505
           -carB
                    -4
                    -5

目标是根据节点属性对我的 XML 进行排序,首先按页数,然后按 zip,然后按运营商。然后,我需要循环浏览结果列表并按特定顺序处理每个索赔。我无法为 3 个嵌套组获取正确的语法。我已经完成了获得 2 个嵌套组,任何人都可以帮助我获得第三个。

到目前为止,这是我的代码。

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;

【问题讨论】:

  • 您给出的输出似乎与您发布的输入不同。如果关系更明显,可能会更容易回答。
  • 示例中C车和D车在哪里?
  • 对不起,我只是把随机数据放在一起,我已经修好了。现在应该一起去
  • 来吧,让一个人休息一下 - 问题是什么:“首先按页数,然后按 zip,然后按运营商”
  • stackoverflow.com/questions/9777885/… 以来发生了什么变化?

标签: c# .net xml linq-to-xml nested-groups


【解决方案1】:

我不确定如何使用 XML 执行此操作,但如果您已经将声明转换为某种类型的数组 Claim(例如,在代码中,claims 的类型为 Claim[]Claim 类型具有称为 KeyCarrierZipPages 的属性或字段,那么这应该可以工作。

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

它不是很干净,但它可以工作。您可以选择具有给定页面、邮编和运营商的声明,如下所示:

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

我选择为您提供一种翻译成 Dictionary&lt;TKey, TValue&gt; 而不是 List&lt;T&gt; 的方法,因为翻译成 List 会丢失密钥,因此获取密钥(页面、拉链或载体)的唯一方法是遍历可能会变得丑陋和复杂的列表。抱歉,如果字典不适合您。

【讨论】:

    【解决方案2】:

    如果没有别的,我相信这段代码可以回答你的问题。必须处理四个嵌套列表非常复杂,如果您可以将解决方案重构为更简单的东西,您可能会发现您的代码将更易于维护。

    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""/>
    </root>";
    
    var xElement = XElement.Parse(xml);
    
    var claims = xElement
      .Elements("Claim")
      .Select(
        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)
            .ToList()
          )
          .ToList()
        )
        .ToList()
      )
      .ToList();
    

    【讨论】:

    • 这种方式看起来行得通,但是除了在我拥有的 LINQ 语句中添加另一个组之外,您采用这种方式有什么原因吗?
    • 对我来说,你的问题不是那么容易理解,所以我尝试编写自己的代码来更好地理解你想要做什么。此外,您在我开始处理我的答案后添加了您的代码。
    • 假设我想订购这些组,以便如果三个运营商组包含 1 个声明,另外 2 个运营商组包含 2 个声明,则具有 1 个声明的运营商组列在具有 2 个名称的运营商组之前。这需要在订购拉链后进行。所以基本上我们不需要按承运人名称而是按组大小排序的承运人组。这种设置可以实现吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 2015-02-10
    • 1970-01-01
    相关资源
    最近更新 更多