使用for从列表中删除节点
本文关键字:删除 节点 列表 for 使用 | 更新日期: 2023-09-27 18:05:44
我是这样做的:
// this is an example of my function, the string and the remover should be variables
string delimeter = ",";
string remover="4";
string[] separator = new string[] { "," };
List<String> List = "1,2,3,4,5,6".Split(separator, StringSplitOptions.None).ToList();
for (int i = 0; i < List.Count - 1; i++)
{
if(List[i]==remover)
List.RemoveAt(i);
}
string allStrings = (List.Aggregate((i, j) => i + delimeter + j));
return allStrings;
问题是返回的字符串与原始字符串相同,与"1,2,3,4,5,6"相同。"4"还在里面
如何修复?
编辑:的解决方案是,我没有检查列表的最后一个节点在这个例子中,它看起来不像因为它是我刚才给出的一个例子
当你像这样从列表中删除项目时,你应该让你的for循环反向运行,从最高索引到最低索引。
如果你从最低到最高,你将最终移动的项目,因为他们被删除,这将跳过项目。反向运行则没有此问题。
您的代码将生成预期的输出。当运行它时,它将返回1,2,3,5,6
。如果没有,那是因为你调用这个方法的方法有问题。
这并不是说你没有问题。
当你删除一个项时,你仍然增加当前索引,所以你跳过了在你删除的任何项之后检查项。
虽然有许多解决方案,但这里最好的解决方案是使用List
的RemoveAll
方法。它不仅确保所有项目都被评估,而且可以更有效地做到这一点。从列表中删除一个项目意味着将所有项目移动一个。RemoveAll
可以在最后完成所有的移动,如果移除很多项目,这将更有效率。
另一个bug是你的for
循环根本不检查最后一项。
附带说明,您不应该使用Aggregate
将给定分隔符的一堆字符串连接在一起。这是非常低效的,因为您需要在添加第二项时将第一项中的所有数据复制到中间字符串中,然后在添加第三项时将这两个数据都复制到一个新字符串中,然后在创建第四个时将所有三个复制到一个新字符串中,以此类推。相反,您应该使用string.Join(delimeter, List);
,它不仅方式更有效,而且更容易编写,并且在语义上准确地表示您要做的事情。双赢双赢
我们现在可以把这个方法重写为:
string delimeter = ",";
string remover = "4";
List<String> List = "1,2,3,4,5,6"
.Split(new[] { delimeter }, StringSplitOptions.None).ToList();
List.RemoveAll(n => n == remover);
return string.Join(delimeter, List);
另一个选择是避免创建一个列表,只是为了从中删除项目,然后再次聚合数据。我们可以把我们拥有的项目序列,只取出我们想要保留的项目,而不是删除我们不想要保留的项目,然后汇总这些项目。这在功能上是相同的,但是删除了不必要的构建列表和删除项的工作,从需求中提取机制:
string delimeter = ",";
string remover = "4";
var items = "1,2,3,4,5,6"
.Split(new[] { delimeter }, StringSplitOptions.None)
.Where(n => n != remover);
return string.Join(delimeter, items);
删除
list.RemoveAll(f => f==remover);