我们说我有一个列表,消息,有三个项目。我不想循环浏览它们并一次删除一个项目。
for (int i = 0; i < messages.Count; i++)
{
messages.RemoveAt(i);
}
(我已删除了大量不相关的代码)
第一次迭代后剩余的消息会发生什么?它们是移动到另一个索引还是我可以这样删除所有三条消息?
谢谢
答案 0 :(得分:9)
您删除的索引后面的所有元素的索引将递减。 如果你想通过循环避免这种情况,让它反向运行(从最高索引删除到最低)。
for (int i = messages.Count - 1; i >= 0; i--)
{
messages.RemoveAt(i);
}
或只是使用
messages.Clear()
一次删除所有元素而不关心任何索引。
如果您只想清除列表,使用Clear
也会更有效,因为它是O(n)操作。 RemoveAt
也是O(n),但在另一个O(n)循环内部使其成为O(n ^ 2) - 并不是因为在你的例子中提到了3个元素,而是在讨论更大的列表时肯定会有所作为。
答案 1 :(得分:3)
在您的代码中,只需拨打messages.Clear();
即可。无需单独删除每个元素。
您的代码将跳过所有其他元素,因为它会删除它们,直到不再满足for
循环的条件。它将删除索引0和2处的元素,因为您说您的集合有三个元素。
让我们逐步完成您的算法:
最初,该列表有三个项目,列出其索引:0:“Hello”,1:“World”,2:“Foo”。
你的循环删除索引0处的元素。列表现在看起来像这样:
0:“世界”,1:“Foo”
然而,你的循环再次执行,因为i
现在等于1和1 < 2
。然后删除索引1处的元素:
0:“世界”
i
增加到2并且不再满足条件(i
不小于1)。您的列表现在包含以前的第二个元素。
答案 2 :(得分:3)
您需要迭代向后
for (int i = messages.Count - 1; i >=0; i--)
{
messages.RemoveAt(i);
}
因为在您当前的循环中,如果您的列表包含3个项目,您将被留下一次。
如果您要从列表中删除所有项目,则可以使用方法List<T>.RemoveAll Method
答案 3 :(得分:1)
他们搬了,see MSDN on List<T>.RemoveAt
method:
当您调用RemoveAt删除项目时,中的剩余项目 列表重新编号以替换已删除的项目。例如,如果你 删除索引3处的项目,索引4处的项目移动到3 位置。
要删除所有元素,Clear
method更合适。
答案 4 :(得分:0)
通过反向循环..
for(int i = messages.Count - 1; i >= 0 ; i--) {
messages.RemoveAt(i);
}
答案 5 :(得分:0)
.NET Reference Source具有以下RemoveAt方法定义:
public void RemoveAt(int index)
{
if ((uint)index >= (uint)_size)
ThrowHelper.ThrowArgumentOutOfRangeException();
Contract.EndContractBlock();
_size--;
if (index < _size)
Array.Copy(_items, index + 1, _items, index, _size - index);
_items[_size] = default(T);
_version++;
}
正如您所看到的 - 如果您删除的项目不是最后一次复制数组项目(从索引+ 1到结束移动的所有项目)。因此,在您的情况下,最好从最后删除项目以避免每次迭代时进行数组复制:
for (int i = messages.Count - 1; i >= 0; i--)
{
messages.RemoveAt(i);
}
如果你想在没有额外逻辑的情况下删除它们,只需调用messages.Clear()
- 在这种情况下,内部数组刚刚清除,大小设置为零。
答案 6 :(得分:0)
您可以将其更改为始终删除第一个
List<string> messages = new List<string>();
messages.Add("a");
messages.Add("b");
messages.Add("c");
for (int i = 0; i < messages.Count; i++)
{
messages.RemoveAt(0);
}
或在一个陈述中清除整个列表
messages.Clear()
答案 7 :(得分:0)
与其他帖子一样,您需要向后迭代
您有很多解决方案可以删除这些项目
messages.Clear();
或
while(messages.Count != 0){
message.RemoveAt(0);
}