我写了一个函数来浏览列表并删除列表项,如果满足某些条件。我的程序崩溃了,过了一会儿我得出结论,外部for循环,遍历列表中的所有项目。 在相同的例行程序中,项目列表可以缩短。
// Lijst is a list of a struct that contains a value .scanned and .price
for (int i = 0; i < Lijst.Count; i++)
{
if (Lijst[i].scanned == false)
{
// (removed deletion of list item i here)
if (Lijst[i].price > (int)nudMinimum.Value)
{
Totaal++;
lblDebug.Text = Totaal.ToString();
}
Lijst.RemoveAt(i); //<-moved to here
}
}
现在我想知道这样做是否正确,而不会使索引超出范围错误。
答案 0 :(得分:2)
为什么不直接List<T>.RemoveAll()
?
https://msdn.microsoft.com/en-us/library/wdka673a(v=vs.110).aspx
在你的情况下
Lijst.RemoveAll(item => some condition);
E.g。
// Count all the not scanned items each of them exceeds nudMinimum.Value
lblDebug.Text = Lijst
.Where(item => !item.scanned && item.price > (int)nudMinimum.Value)
.Count()
.ToString();
// Remove all not scanned items
Lijst.RemoveAll(item => !item.scanned);
答案 1 :(得分:1)
你可能正在寻找这个
for (int i = Lijst.Count - 1 ; i >= 0 ; i--)
{
if (Lijst[i].scanned == false)
{
if (Lijst[i].price > (int)nudMinimum.Value)
{
Totaal++;
lblDebug.Text = Totaal.ToString();
}
Lijst.RemoveAt(i);
}
}
评论中的问题:
为什么循环的另一个方向会起作用?
因为当循环从零运行到计数时当索引无法删除并且仍然保留计数时会出现这种情况。例如:
如果List中有10个项目,循环从0开始,将删除0,1,2,3,4,现在左边的项目是5,索引也是5,它也将删除该项目。之后,当循环值达到6并且项目左边是4.那么它会产生问题。它会引发错误。即指数超出范围
答案 2 :(得分:1)
问题是,当你删除元素编号5时,列表会变短,元素编号6现在是5,编号7变为第6等。但是,如果向后运行循环,则数字将按预期保留。
for(int i = donkeys.Count - 1; i >= 0; i++)
if(donkeys[i] == some condition here)
donkeys.RemoveAt(i);
然而,这是一个像老板一样的方法。有更好的方法。您已经得到了答案,但我想建议一种基于LINQ的方法。
int Totaal = Lijst
.Where(item => item.scanned)
.Where(item => item.price > (int)nudMinimum.Value)
.Count();
Lijst = Lijst.Where(item => !item.scanned).ToList()
另外,作为旁注,我想知道你是否觉得下面的内容更具可读性。考虑以下不同的命名(关于语言和大写)。
List<Item> items = ...;
int minimum = (int)nudMinimum.Value;
int total = items
.Where(item => item.scanned)
.Where(item => item.price > minimum)
.Count();
items = items
.Where(item => !item.scanned)
.ToList();
答案 3 :(得分:1)
你去吧
// 1. Count items
lblDebug.Text = Lijst.Count(x => x.price > (int)nudMinimum.Value && !x.scanned).ToString();
//2. Remove items
Lijst.RemoveAll(x => !x.scanned);
答案 4 :(得分:1)
首先您要删除索引为i的元素,然后使用它。您需要首先使用具有索引i的元素执行您的过程,然后将其删除。您的代码如下所示:
for (int i = 0; i < Lijst.Count; i++)
{
if (Lijst[i].scanned == false)
{
if (Lijst[i].price > (int)nudMinimum.Value)
{
Totaal++;
lblDebug.Text = Totaal.ToString();
}
Lijst.RemoveAt(i);
}
}
答案 5 :(得分:0)
通常,如果您要从列表中删除与谓词匹配的所有项目,请使用List<T>.RemoveAll()
,例如:
List<int> test = Enumerable.Range(0, 10).ToList();
test.RemoveAll(value => value%2 == 0); // Remove all even numbers.
Console.WriteLine(string.Join(", ", test));
但是,您似乎需要进行一些额外的处理。你有两个选择:
RemoveAll()
删除不需要的项目,然后循环遍历列表以分别处理剩余项目。List.Count-1
向后循环到0
。答案 6 :(得分:0)
你的代码有些不正确的格式。 首先,您删除了列表项,然后您试图捕获该已删除项的价格。 怎么可能。
所以你可以用这种方式写作。
for (int i = 0; i < Lijst.Count; i++)
{
if (Lijst[i].scanned == false)
{
if (Lijst[i].price > (int)nudMinimum.Value)
{
Totaal++;
lblDebug.Text = Totaal.ToString();
}
Lijst.RemoveAt(i);
}
}
答案 7 :(得分:-1)
List<string> list = new List<string>();
list.Add("sasa");
list.Add("sames");
list.Add("samu");
list.Add("james");
for (int i = list.Count - 1; i >= 0; i--)
{
list.RemoveAt(i);
}