我得到了一个9MB大的XML文件。显然,它坏了。
我想检查在任何级别2的同级元素上是否有一个具有相同值的属性"Id"。
目前进展太慢。我可以对此代码进行什么样的优化?
编辑后包含一些提示
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 _pathToXml=@"C:44";
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);
}
}
}
您说要检查级别2的子体,但FindDupes是递归的,所以每次调用都要在foreach循环中递归检查两个级别。
您正在重复检查事物,因此可以执行int j = i+1
而不是从0开始。
您不必检查i != j
,然后检查
-
在for循环中,将列表计数存储到变量中,而不是访问count属性。
for(int i=0,idCount=ids.Count;i++){}
-
将ids[i]存储到本地变量,而不是在集合中多次查找它。
- 最大的变化是避免嵌套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