我对下面显示的代码有问题。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace problem2
{
class Program
{
static void Main(string[] args)
{
int[] nums = Console.ReadLine().Split().Select(int.Parse).ToArray();
List<int> lst = nums.OfType<int>().ToList();
while (true)
{
string des = Console.ReadLine();
var output = Regex.Replace(des.Split(" ")[0], @"[^0-9a-zA-Z\ ]+", "");
if (output == "Add")
{
string val = Regex.Replace(des, "[^0-9]", "");
int value = int.Parse(val);
lst.Add(value);
}
else if(output == "Remove")
{
string val = Regex.Replace(des, "[^0-9]", "");
int value = int.Parse(val);
lst.Remove(value);
}else if(output == "Replace")
{
String result1 = System.Text.RegularExpressions.Regex.Match(des, @"\d+").Value;
var lastno = des.Split().Last();
List<int> lst2 = lst;
for (int i = 0; i < lst2.Count; i++)
{
if(lst[i] == int.Parse(result1))
{
lst[i] = int.Parse(lastno);
break;
}
}
lst = lst2;
}
else if(output == "Collapse")
{
string val = Regex.Replace(des, "[^0-9]", "");
int value = int.Parse(val);
for(int i = 0; i < lst.Count; i+=1)
{
int element = (int)lst[i];
if (element < value)
{
lst.RemoveAt(i);
}
else
{
continue;
}
}
}else if (output == "Mort")
{
PrintValues(lst);
break;
}
}
}
public static void PrintValues(IEnumerable myList)
{
foreach (Object obj in myList)
Console.Write("{0} ", obj);
Console.WriteLine();
}
}
}
这部分代码更准确:
else if(output == "Collapse")
{
string val = Regex.Replace(des, "[^0-9]", "");
int value = int.Parse(val);
for(int i = 0; i < lst.Count; i+=1)
{
int element = (int)lst[i];
if (element < value)
{
lst.RemoveAt(i);
}
else
{
continue;
}
}
我尝试了各种选项,但循环遗漏了元素。举个例子
entrance:
1 2 -1 0 -3 9 8 7 2
Collapse 8
Mort
output:
9 8
但程序给了我这个输出:
2 0 9 8 2
我试图通过调试器查看问题所在,发现循环丢失了元素
答案 0 :(得分:1)
您正在修改正在迭代的集合。这会将元素移动到其他索引并使您为 i
标头中的后续元素确定的 for
无效。更好地向后循环
for (int i = lst.Count - 1; i >= 0; i--) {
// Now you can safely remove (or add) elements without affecting
// the index of non yet processed elements.
}
您仍在修改前面元素的索引,但现在正在向后移动。
在 Visual Studio 中,您可以使用 forr
代码段创建反向 for 循环。输入
forr
(当然还有用于普通 for 循环的 for
代码片段。它将使用 i++
而不是 i += 1
来增加索引。)
此外,如果列表很长并且您要删除许多元素,则值得考虑性能。这种方法可以移动大量元素。在这种情况下,将要保留的元素复制到新列表(使用适当的初始容量进行初始化)会更有效。
答案 1 :(得分:1)
详细说明@Berkay 的评论:您在循环时更改了列表。如果 i 是 2 并且您删除该元素,那么曾经位于索引 3 的元素现在变为 2,依此类推。他递减 i
的方法会奏效。另一种方法是改用 linq .Where
语句:
var newList = lst.Where(e=> e>=value).ToList();
答案 2 :(得分:1)
应该是,
for(int i = 0; i < lst.Count; i+=1)
{
int element = (int)lst[i];
if (element < value)
{
lst.RemoveAt(i);
i--;
}
else
{
continue;
}
}
正如评论中提到的@David784。当您从迭代集合中删除元素时。每次删除 i 项后,您都会错过 1 个元素。