2017-04-22 58 views
1

我有两个班让我们说多个GROUPBY LINQ的

class Foo 
{ 
List<Bar> Bars{get;set;} 
} 

class Bar 
{ 
    string Name{get;set;} 
    string Value{get;set;} 
} 

,我有这样的

var resultsGroupedByState=Foos.GroupBy(x=>x.Bars.First(c=>c.Name=="state").Value); 

,将返回各州分组结果的查询的GroupBy的结果,而且用户可以定义通过字段例如组的层级

  1. GROUPBY国家
  2. GROUPBY县
  3. GROUPBY市等

多少GROUPBY我已经做的水平,我不知道前期。我必须先在层次结构中定义一个groupby,然后根据第一个groupby的结果中的第二个层次结构中的第二个值进行groupby,然后继续。

最后我必须从这样的数据生成一个XML。

<State value="anyState"> 
    <County value="anyCounty"> 
     <City value="anyCity"> 
      .......... 
     </City> 
    </County> 
</State> 

回答

1

基本上你需要生成XML。一种解决方案可以是递归地执行GroupBy并直接创建XMLDocument

这是一个可以做到这一点的助手类。

public class XmlGenerator 
{ 
    private XmlDocument _document; 
    private List<string> _fields; 
    private int index = 0; 

    public XmlGenerator(List<string> fields) 
    { 
     _fields = fields; 
    } 

    public void GenerateXML(IEnumerable<Foo> lookupData, XmlElement root, string field) 
    { 
     var fieldGrouping = lookupData.GroupBy(v => v.Bars.First(x => x.Name == field).Value); 
     foreach (var grouping in fieldGrouping) 
     { 
      var element = _document.CreateElement(field); 
      var attrib = _document.CreateAttribute("value"); 
      attrib.InnerText = grouping.Key; 

      element.Attributes.Append(attrib); 
      root.AppendChild(element); 

      // If that is last field. No need to do any grouping. 
      if (index < _fields.Count - 1) 
      { 
       // After each nested call update the nested level. 
       // If GenerateXML do another that will be upon next nested level 
       index += 1; 
       GenerateXML(grouping, element, _fields[index]); 
       index -= 1; 
       // Make sure to change back nested level index otherwise that will not works if you have multiple groups. 
      } 
     } 
    } 

    public string GenerateXML(IEnumerable<Foo> lookupData) 
    { 
     _document = new XmlDocument(); 
     var root = _document.CreateElement("Root"); 
     _document.AppendChild(root); 
     index = 0; 

     GenerateXML(lookupData, root, _fields[index]); 

     return _document.OuterXml; 
    } 
} 

其实我已经在这里做了什么,我一直保存在里面List<string>.领域的所有列表,并通过特定的领域写了一个辅助方法组。每次通过时,我都会传递需要分组的方法数据以及您想要分组的字段的名称。

希望如此,解决您的问题。

+0

谢谢指出我一直在寻找的解决方案,但我坚持先制作该层次,然后迭代通过它来生成XML,反正它解决了我的问题。 – Aarif

-1

您不需要GrroupBy。试试这个

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string xml = 
       "<Root>" + 
        "<State value=\"AState\">" + 
         "<County value=\"ACounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
         "<County value=\"BCounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
         "<County value=\"CCounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
        "</State>" + 
        "<State value=\"BState\">" + 
         "<County value=\"ACounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
         "<County value=\"BCounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
         "<County value=\"CCounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
        "</State>" + 
        "<State value=\"CState\">" + 
         "<County value=\"ACounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
         "<County value=\"BCounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
         "<County value=\"CCounty\">" + 
          "<City value=\"ACity\"/>" + 
          "<City value=\"BCity\"/>" + 
          "<City value=\"CCity\"/>" + 
         "</County>" + 
        "</State>" + 
        "</Root>"; 

      XElement root = XElement.Parse(xml); 

      List<Foo> foos = Helper(root); 

     } 
     public static List<Foo> Helper(XElement element) 
     { 
      if (element.HasElements) 
      { 
       string tagName = ((XElement)element.FirstNode).Name.LocalName; 

       List<Foo> children = element.Elements(tagName).Select(x => new Foo() 
       { 
        Name = tagName, 
        Value = (string)x.Attribute("value"), 
        foos = Helper(x) 
       }).ToList(); 


       return children; 
      } 
      else 
      { 
       return null; 
      } 
     } 
    } 
    public class Foo 
    { 
     public string Name { get; set; } 
     public string Value { get; set; } 

     public List<Foo> foos { get; set; } 
    } 

} 
+0

虽然此代码片段可能回答OP的问题,但如果您添加解释,答案会更有用。请注意,仅有代码的答案往往会被标记为质量审查,这可能会导致它们被删除。 –

+0

此代码从xml到Foos列表。我认为这个问题正好相反:从Foos列表到xml。 – vyrp

+0

是啊@vyrp是正确的,你的解决方案是我想要的相反。无论如何谢谢你的努力 – Aarif