我编写了以下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";
}
答案 0 :(得分:1)
要做的第一件事就是抓住一个分析器,看看代码的哪个区域运行时间过长,请尝试http://www.jetbrains.com/profiler/或http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/。
在确定问题出在何处之前,您永远不应该开始进行性能调整。
如果问题出在linq查询中,那么你可以尝试对intlist进行排序并对要删除的每个项进行二进制搜索,尽管你可能会使用正确的linq查询获得类似的行为。
答案 1 :(得分:0)
答案 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函数,因为它们已经过性能测试。