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即使这根本不能回答问题,可读性可能比可能微不足道的性能差异更重要。这应该比问题中提出的两种解决方案具有更好的性能。