2012-03-18 4 views
0

У меня есть XML-файл размером 9 МБ. По-видимому, он сломан.Любые советы по оптимизации этой крошечной функции C#?

Я хочу проверить, есть ли на каком-либо уровне 2 родственных элемента атрибут «Id» с одинаковым значением.

В настоящее время идет слишком медленно. Какие оптимизации я могу сделать для этого кода?

Edited включить некоторые советы

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

+1

Для действительно больших файлов XML я бы использовал [XmlReader] ('http: // msdn. microsoft.com/en-us/library/system.xml.xmlreader% 28v = vs.100% 29.aspx') вместо 'XDocument'. – Vlad

+0

вы можете сделать int j = i + 1, а не начинать с 0 –

ответ

2

Вы скажем, вы хотите проверить потомки второго уровня, но все же FindDupes является рекурсивным, поэтому вы рекурсивно проверяете два уровня в глубине петель foreach, каждый вызов.

1

вы повторить проверки вещей, так что вы могли бы сделать int j = i+1 вместо начиная с 0.

вы не должны проверить i != j затем

1
  1. В ваших циклах для записи хранятся список с переменной, а не доступ к счету имущество.

    для (INT I = 0, idCount = ids.Count; я ++) { }

  2. магазин Идентификаторы [I] к локальной переменной, вместо того, чтобы искать его в коллекции более чем один раз.

  3. Самым большим изменением было бы избежать вложенных циклов. Подумайте о переписывании.

Редактировать: Сделано следующие изменения.

 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 Мб файла здесь является раз:

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

Как избежать вложенных циклов? –

+0

Пожалуйста, разместите пример вашего xml-файла. – Coding101

+0

любой xml будет делать, что имеет несколько элементов-братьев с теми же ценными атрибутами «Id» –

Смежные вопросы