List.RemoveAt(index)是如何工作的?
本文关键字:工作 何工作 RemoveAt index List | 更新日期: 2023-09-27 17:51:03
假设我有一个列表,消息,有三个项目。我不想循环遍历它们,每次删除一个项。
for (int i = 0; i < messages.Count; i++)
{
messages.RemoveAt(i);
}
(我已经删除了很多不相关的代码)
第一次迭代之后剩下的消息会发生什么?它们是否被移动到另一个索引中,或者我可以这样做以删除所有三条消息?
谢谢
您删除的索引后面的所有元素的索引将被递减。如果你想在循环中避免这种情况,让它反向运行(从最高索引到最低索引删除)。
for (int i = messages.Count - 1; i >= 0; i--)
{
messages.RemoveAt(i);
}
或者直接用
messages.Clear()
一次删除所有元素,而不考虑任何索引。
如果你只想清除List,使用Clear
也更有效,因为它是一个O(n)操作。RemoveAt
也是O(n),但在另一个O(n)循环中使它成为O(n^2) -这与你的例子中提到的3个元素无关,但当谈论更大的列表时,它肯定会有所不同。
在您的代码中,调用messages.Clear();
更简单。没有必要单独删除每个元素。
您的代码将跳过所有其他元素,因为它删除它们,直到for
循环的条件不再满足。它将删除索引0和2处的元素,因为您说您的集合有三个元素。
让我们通过你的算法:
最初,列表有三个项目,按它们的索引列出:0:"Hello",1:"World"和2:"Foo"。
循环删除索引0处的元素。列表现在看起来像这样:
0: "World", 1: "Foo"
然而,你的循环再次执行,因为i
现在等于1和1 < 2
。然后删除索引1处的元素:
0:"世界"
i
被增加到2,并且不再满足条件(i
不小于1)。你的列表现在由原来的第二个元素组成。
需要反向迭代
for (int i = messages.Count - 1; i >=0; i--)
{
messages.RemoveAt(i);
}
因为在当前循环中,如果列表包含3个项目,则只剩下一次。
如果你想从列表中删除所有项目,那么有一个方法List<T>.RemoveAll Method
它们被移动了,参见MSDN on List<T>.RemoveAt
method:
当你调用RemoveAt来删除一个项时,中剩余的项列表被重新编号以替换被删除的项。例如,如果你删除索引3处的项,将索引4处的项移到3处位置。
删除所有元素,Clear
方法更合适。
执行反向循环…
for(int i = messages.Count - 1; i >= 0 ; i--) {
messages.RemoveAt(i);
}
你可以把它改成总是删除第一个
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()
。. NET参考源代码中有以下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()
,如果你想删除它们而不需要额外的逻辑-在这种情况下,内部数组刚刚被清除,大小设置为零。
与其他帖子一样,您需要向后迭代
你有很多方法来删除项目
messages.Clear();
或
while(messages.Count != 0){
message.RemoveAt(0);
}