这个微小的c函数的任何优化提示

本文关键字:任何 优化 提示 函数 | 更新日期: 2023-09-27 18:28:23

我得到了一个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:'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);
    }
  }
}

这个微小的c函数的任何优化提示

您说要检查级别2的子体,但FindDupes是递归的,所以每次调用都要在foreach循环中递归检查两个级别。

您正在重复检查事物,因此可以执行int j = i+1而不是从0开始。

您不必检查i != j,然后检查

  1. 在for循环中,将列表计数存储到变量中,而不是访问count属性。

    for(int i=0,idCount=ids.Count;i++){}

  2. 将ids[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