2012-03-18 74 views
0

我有一個XML文件,爲9MB大。顯然,它被打破了。這個微小的c#函數的任何優化技巧?

我要檢查,如果在任意級別2兄弟元素有一個屬性「身份證」具有相同的值。

目前它去太慢。我可以對此代碼進行哪些優化?

編輯,包括一些提示

namespace ConsoleApplication1{ 
    using System; 
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.IO; 
    using System.Linq; 
    using System.Xml.Linq; 
    internal class Program{ 
    private const string [email protected]"C:\4\4"; 
    private static readonly List<object> _duplicateLeafs=new List<object>(); 
    private static void Main(){ 
     var xml=ReadXml(); 
     var elements=xml.Descendants(); 
     foreach(var element in elements) 
     FindDupes(element); 
     Console.ReadLine(); 
     Debugger.Break(); 
    } 
    private static XDocument ReadXml(){ 
     return XDocument.Parse(File.ReadAllText(_pathToXml)); 
    } 
    private static void FindDupes(XElement element){ 
     var elements=element.Descendants(); 
     var elementsWithIds=elements.Where(x=>x.Attribute("Id")!=null); 
     var ids=elementsWithIds.Select(x=>x.Attribute("Id")).ToList(); 
     for(var i=0;i<ids.Count;i++) 
     for(var j=i+1;j<ids.Count;j++) 
      if(i!=j&&ids[i]==ids[j]) 
      _duplicateLeafs.Add(elementsWithIds.First(x=>x.Attribute("Id")==ids[i])); 
     foreach(var subElement in elements) 
     FindDupes(subElement); 
    } 
    } 
} 
+4

使用XmlReader並按順序處理它,而不是完整地解析它以便開始(這就是XDocument.Parse所做的) – 2012-03-18 23:39:31

+1

對於非常大的XML文件,我會使用[XmlReader]('http:// msdn。 microsoft.com/en-us/library/system.xml.xmlreader%28v = vs.100%29.aspx')而不是'XDocument'。 – Vlad 2012-03-18 23:40:50

+0

你可以做int j = i + 1而不是從0開始 – 2012-03-18 23:42:44

回答

2

你說你想檢查2級後代,但FindDupes是遞歸的,所以你遞歸地檢查foreach循環中的兩個級別,每個調用。

1

你重複檢查的事情,所以你可以做int j = i+1,而不是在0

開始你就不必檢查i != j然後

1
  1. 在你的for循環存儲列表計數的變量,而不是訪問計數屬性。

    對(INT I = 0,idCount = ids.Count;我++){ }

  2. 商店的ID [I]到本地變量,而不是尋找它收集在一次以上。

  3. 最大的變化是避免嵌套的for循環。考慮重寫。

編輯:做了如下的變化。

 private const string _pathToXml = @"C:\test.xml"; 
     private static readonly List<object> _duplicateLeafs = new List<object>(); 
     private static void Main() 
     { 
      var xml = ReadXml(); 
      var elements = xml.Descendants(); 
      FindDupes(elements); 
     } 

     private static void FindDupes(IEnumerable<XElement> elements) 
     { 
      foreach (var element in elements) 
      { 
       var subElements = element.Descendants(); 
       var subElementsWithIds = subElements.Where(x => x.Attribute("Id") != null).ToList(); 
       var ids = subElementsWithIds.Select(x => x.Attribute("Id")).ToList(); 
       var duplicates = ids.GroupBy(s => s.Value).SelectMany(grp => grp.Skip(1)).Distinct().ToList(); 

       if (duplicates != null) 
       { 
        _duplicateLeafs.AddRange(duplicates); 
       } 
       FindDupes(subElements); 
      } 
     } 

使用下面的XML文件:

<?xml version="1.0" encoding="utf-8" ?> 
<persons> 
    <person Id="1"> 
    <name>Michael</name> 
    <age>29</age> 
    </person> 
    <person Id="1"> 
    <name>Rebecca</name> 
    <age>29</age> 
    </person> 
    <person Id="2"> 
    <name>Matthew</name> 
    <age>29</age> 
    </person> 
    <person Id="2"> 
    <name>Paul</name> 
    <age>29</age> 
    </person> 
</persons> 

測試您的最新版本,我提供的代碼後,在加載此16 MB的文件是時代:

Time: 2.8704708 seconds Lambda solution 
Time: 692.043006 seconds Nested for loops 
+0

如何避免嵌套for循環? – 2012-03-18 23:47:19

+0

請發佈你的xml文件的例子。 – Coding101 2012-03-18 23:58:29

+0

任何xml都會這樣做,它有一些具有相同「Id」屬性值的同胞元素 – 2012-03-19 00:04:12