改进性能代码?

时间:2011-10-10 08:08:23

标签: c#

我编写了以下c#代码来生成一组数字,然后与另一组数字进行比较以删除不需要的数字。

但是它在运行时花了太长时间来完成这个过程。以下是文件背后的代码。

它必须生成的数字大小为7个数字,我用它删除的数字列表大约有700个数字。

有没有办法改善运行时性能?

string[] strAry = txtNumbersToBeExc.Text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
    int[] intAry = new int[strAry.Length];
    List<int> intList = new List<int>();
    for (int i = 0; i < strAry.Length; i++)
    {
        intList.Add(int.Parse(strAry[i]));
    }

    List<int> genList = new List<int>();

    for (int i = int.Parse(txtStartSeed.Text); i <= int.Parse(txtEndSeed.Text); i++)
    {
        genList.Add(i);
    }
    lblStatus.Text += "Generated: " + genList.Capacity;

    var finalvar = from s in genList where !intList.Contains(s) select s;

    List<int> finalList = finalvar.ToList();

    foreach (var item in finalList)
    {
        txtGeneratedNum.Text += "959" + item + "\n";
    }

5 个答案:

答案 0 :(得分:1)

要做的第一件事就是抓住一个分析器,看看代码的哪个区域运行时间过长,请尝试http://www.jetbrains.com/profiler/http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/

在确定问题出在何处之前,您永远不应该开始进行性能调整。

如果问题出在linq查询中,那么你可以尝试对intlist进行排序并对要删除的每个项进行二进制搜索,尽管你可能会使用正确的linq查询获得类似的行为。

答案 1 :(得分:0)

  1. 将intList从List更改为HashSet - 在确定条目是否存在时提供更好的性能。
  2. 考虑使用Linq的Enumerable.Intersect,特别是与#1结合使用。

答案 2 :(得分:0)

为什么不在解析int时进行包含检查,只需构建结果列表directley。

迭代列表两次没有多大意义。事实上,为什么要建立中间列表!?!直接写一个StringBuilder,因为换行符分隔的字符串似乎是你的目标。

string [] strAry = txtNumbersToBeExc.Text.Split(new string [] {Environment.NewLine},StringSplitOptions.RemoveEmptyEntries);

var exclusions = new HashSet<T>();
foreach (string s in txtNumbersToBeExc.Text.Split(new string[] { Environment.NewLine })
{
    int value;
    if (int.TryParse(s, value)
    {
        exclusions.Add(value);
    }
}


var output = new StringBuilder();
for (int i = int.Parse(txtStartSeed.Text); i <= int.Parse(txtEndSeed.Text); i++)
{
    if (!exclusions.Contains(i))
    {
        output.AppendFormat("959{0}\n", i);
    }
}

txtGeneratedNum.Text = output.ToString();

答案 3 :(得分:0)

使用以下代码更改创建genList的代码块:

List<int> genList = new List<int>(); 

    for (int i = int.Parse(txtStartSeed.Text); i <= int.Parse(txtEndSeed.Text); i++) 
    { 
        if (!intList.Contains(i)) genList.Add(i); 
    } 

并在txtGeneratedNum上创建genList循环后。这将减少实施的循环次数。

答案 4 :(得分:0)

    string numbersStr = txtNumbersToBeExc.Text;
    string startSeedStr = txtStartSeed.Text;
    string endSeedStr = txtEndSeed.Text;


    //next, the input type actually is of type int, we should test if the strings are ok ( they do represent ints)
    var intAry = numbersStr.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Select(s=>Int32.Parse(s));   
    int startSeed = Int32.Parse(startSeedStr);
    int endSeed = Int32.Parse(endSeedStr);

    /*FROM HERE*/
    // using Enumerable.Range 
    var genList = Enumerable.Range(startSeed, endSeed - startSeed + 1);

    // we can use linq except
    var finalList = genList.Except(intAry);

    // do you need a string, for 700 concatenations I would suggest StringBuilder
    var sb = new StringBuilder();
    foreach ( var item in finalList)
    {
        sb.AppendLine(string.Concat("959",item.ToString()));
    }
    var finalString = sb.ToString();
    /*TO HERE, refactor it into a method or class*/

    txtGeneratedNum.Text = finalString;

它们的关键点是String是一个不可变类,因此两个字符串之间的“+”操作将创建另一个字符串。 StringBuilder它没有这样做。在你的情况下,如果你使用for循环,foreach循环,linq花哨的函数来完成排除,这无关紧要。性能受损是因为字符串连接。我更信任System.Linq函数,因为它们已经过性能测试。