2017-04-22 98 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