从List中删除特定的字符串值

时间:2013-06-06 11:11:28

标签: c# list

我有一个字符串值列表,其中一些值包含前面的xxx或XXX。

xxxRed
xxxYellow
xxxxCareful with that axe Eugene!
xxxxxxdedicum aceasta frumoasa Melodia
xxxxLeaders
xxxxWorking Around - titles
XXXXXNothing To Fear
xxxxAvoiding standards
xxxFirst Aid

List<string> lstTitles = new List<string>();

这就是我试过的

for (int i=0; i < lstTitles.Count; i++)
            {
                string title = lstTitles[i].ToLower().Trim();
                if (title[0] == 'x')
                {
                    lstTitles.Remove(lstTitles[i]);

                }
            }

我遇到的问题是只删除了部分值但不是全部。

是否有更好的方法可以删除这些值?

6 个答案:

答案 0 :(得分:10)

使用RemoveAll方法

lstTitles.RemoveAll(s => s[0] == 'x' || s[0] == 'X');

您可能希望使用StartsWith而不是比较第一个字符。

lstTitles.RemoveAll(s => s.StartsWith("x",StringComparison.InvariantCultureIgnoreCase));

答案 1 :(得分:3)

  

我遇到的问题是只删除了一些值但不是全部。

因为你正在跳过物品。当您致电Remove()时,下一个项目将位于索引i,但您将在下一个循环中增加i

可以通过迭代列表的副本,并删除原始文件中不需要的项目来解决:

foreach (var item in lstTitles.ToList())
{
    if (item.StartsWith("x", StringComparison.InvariantCultureIgnoreCase))
    {
        lstTitles.Remove(item);
    }
}

虽然这涉及创建列表的副本(这并不是真正有用),但是调用Remove()本身远远不够。

所以你可以反转你的for循环,删除最后的项目,这些项目不会改变未处理项目的索引:

for (int i = lstTitles.Count - 1; i > 0; i--)
{
    if (lstTitles[i].StartsWith("x", StringComparison.InvariantCultureIgnoreCase))
    {
        lstTitles.RemoveAt(i);
    }
}

但正如@ I4V所指出的那样,所有这些逻辑都已经在List<T>.RemoveAll()中,这对于某些边缘情况来说更好,并且可能已经针对某些边缘情况进行了优化,因此再次手动编码它几乎没用。

答案 2 :(得分:2)

那是因为你跳过了价值。

假设您的列表包含['xVal1','xVal2','val3','xVal4','val5']。首先,您的i为0,然后查看列表[0],即'xVal1',以便将其删除。

现在你的列表包含['xVal2','val3','xVal4','val5'],你的i是1.所以你看一下列表[1]这是'val3'。你忽略了xVal2!

您可以从列表的后面开始并转到前面,但如果您删除了相同的值,您仍然会有潜在的错误。

更简单的方法是使用LINQ:

var newList = lstTitles.Where(title=>!title.StartsWith('xxx'))

答案 3 :(得分:2)

您应该使用允许传递ToLower的{​​{1}}重载,而不是StartsWith

然后使用StringComparison.OrdinalIgnoreCase这是最可读,最有效和最短的方法:

List.RemoveAll

Demo

答案 4 :(得分:2)

我认为,您最好以这种方式创建一个新列表

list = list
    .Where(i => ! i.StartsWith("xxx", StringComparison.InvariantCultureIgnoreCase))
    .ToList();

它将具有O(n)复杂度,而试图将1逐个删除将是O(n ^ 2)。

答案 5 :(得分:1)

这也可以起作用:

list.RemoveAll(i => i.StartsWith("xxx", StringComparison.InvariantCultureIgnoreCase));

处理所有案件而没有第二份清单。