C#从字符串中删除重复项的最快方法:拆分与循环
我有一串破折号分隔的数字,我正在从中删除重复的数字C#从字符串中删除重复项的最快方法:拆分与循环,c#,performance,loops,split,duplicates,C#,Performance,Loops,Split,Duplicates,我有一串破折号分隔的数字,我正在从中删除重复的数字 string original = "45-1-3-45-10-3-15"; string new = "45-1-3-10-15"; 我尝试了两种方法,并使用秒表来确定哪种方法更快,但时间流逝不一致,因此我希望了解哪种方法更有效地实现新的无重复列表 方法1:While循环 List<string> temp = new List<string>(); bool more
string original = "45-1-3-45-10-3-15";
string new = "45-1-3-10-15";
我尝试了两种方法,并使用秒表来确定哪种方法更快,但时间流逝不一致,因此我希望了解哪种方法更有效地实现新的无重复列表
方法1:While循环
List<string> temp = new List<string>();
bool moreNumbers = true;
while (moreNumbers)
{
if (original.Contains("-"))
{
string number = original.Substring(0, original.IndexOf("-"));
//don't add if the number is already in the list
int index = temp.FindIndex(item => item == number);
if (index < 0)
temp.Add(value);
original = original.Substring(original.IndexOf("-") + 1);
}
else
moreNumbers = false;
}
//add remaining value in
string lastNumber = original;
//don't add if the number is already in the list
int indexLast = temp.FindIndex(item => item == lastNumber);
if (indexLast < 0)
temp.Add(lastNumber);
string new = "";
foreach (string number in temp)
{
new += "-" + number;
}
if (new[0] == '-')
new = new.Substring(1);
List temp=new List();
布尔-莫尔数=真;
while(更多数字)
{
如果(原始。包含(“-”))
{
字符串编号=original.Substring(0,original.IndexOf(“-”);
//如果号码已在列表中,则不要添加
int index=temp.FindIndex(item=>item==number);
如果(指数<0)
临时增加值;
original=original.Substring(original.IndexOf(“-”)+1);
}
其他的
moreNumbers=false;
}
//在中添加剩余值
字符串lastNumber=原始;
//如果号码已在列表中,则不要添加
int indexLast=temp.FindIndex(item=>item==lastNumber);
if(indexLast<0)
临时添加(最新编号);
字符串new=“”;
foreach(临时值中的字符串编号)
{
新+=“-”+编号;
}
如果(新[0]='-')
新=新的子字符串(1);
方法2:拆分
List<string> temp = original.Split('-').Distinct().ToList();
string new = "";
foreach (string number in temp)
{
new += "-" + number;
}
if (new[0] == '-')
new = new.Substring(1);
List temp=original.Split('-').Distinct().ToList();
字符串new=“”;
foreach(临时值中的字符串编号)
{
新+=“-”+编号;
}
如果(新[0]='-')
新=新的子字符串(1);
我认为第二种方法更具可读性,但可能更慢?以下哪种方法更有效或更好?这将得到高度优化,但您需要测试性能
string result = string.Join("-", original.Split('-').Distinct());
你在两个例子中都有一些低效之处
方法1:操作字符串
永远不会有效。字符串是不可变的
方法2:无需创建列表
并使用StringBuilder()
而不是使用字符串连接
最后,
new
是一个C#保留字,因此您的代码都不会编译。在第一种方法中,您使用了几个子字符串调用和几个IndexOf调用。我不知道具体的内部实现,但我猜它们的时间复杂度是O(n)
因为,对于列表中的每个数字,您将在另一个列表中执行一个完整的循环(使用字符串作为列表),所以时间复杂度为O(n^2)
第二个选项,我假设它也是O(n^2),因为要在IEnumerable中区分列表,它必须迭代列表
我认为解决这个问题的一个最佳方法是:
1) 循环主字符串,对于每个“-”或字符串的结尾,保存数字(这将比拆分在空间上更经济)。
2) 对于每个数字,将其放入字典中。这在空间方面并不经济,但将提供O(1)时间来检查项目是否正确。散列小字符串不应该太频繁。
3) 循环字典以检索不同的值
这个实现将是O(n),比O(n^2)更好
请注意,只有使用字典才能以不同的顺序传递结果字符串。如果顺序很重要,则使用字典检查项目是否重复,但将其放入辅助列表中。同样,这将需要空间成本。测量它。使用@Habib我确实使用了秒表,就像我说的,结果不一致——有时方法1测量速度更快,有时方法2。只是想知道这些方法中哪一种是首选方法?您在发布版本构建和启动时没有附加调试程序吗?顺便说一句,您可以使用
string.Join
来重建字符串,而不是在这两个方法的末尾使用foreach
+if
。您可以编写更简单的方法2:string.Join(“-”,original.Split('-').Distinct())代码>I+1'ed即使这根本不能回答问题,可读性可能比可能微不足道的性能差异更重要。这应该比问题中提出的两种解决方案具有更好的性能。