gpt4 book ai didi

c# - 在迭代列表时从列表中删除/添加项目

转载 作者:可可西里 更新时间:2023-11-01 08:50:44 26 4
gpt4 key购买 nike

首先,我知道由于显而易见的原因,这是不可能开箱即用的。

foreach(string item in myListOfStrings) {
myListOfStrings.Remove(item);
}

上面的片段是我见过的最可怕的事情之一。那么,你如何实现它呢?您可以使用 for 向后遍历列表,但我也不喜欢这种解决方案。

我想知道的是:是否有一种方法/扩展可以从当前列表中返回一个 IEnumerable,类似于 float 副本? LINQ 有很多扩展方法可以做到这一点,但您总是必须用它做一些事情,例如过滤(where, take...)。

我期待这样的事情:

foreach(string item in myListOfStrings.Shadow()) {
myListOfStrings.Remove(item);
}

.Shadow() 在哪里:

public static IEnumerable<T> Shadow<T>(this IEnumerable<T> source) {
return new IEnumerable<T>(source);
// or return source.Copy()
// or return source.TakeAll();
}

示例

foreach(ResponseFlags flag in responseFlagsList.Shadow()) {
switch(flag) {
case ResponseFlags.Case1:
...
case ResponseFlags.Case2:
...
}
...
this.InvokeSomeVoidEvent(flag)
responseFlagsList.Remove(flag);
}

解决方案

我就是这样解决的,效果很好:

public static IEnumerable<T> Shadow<T>(this IEnumerable<T> source) where T: new() {
foreach(T item in source)
yield return item;
}

它不是那么快(很明显),但它是安全的并且正是我想要做的。

最佳答案

由于列表的实现方式,从列表中逐一删除多个元素是 C# 反模式。

当然,可以用for循环(而不是foreach)来完成。或者可以通过制作列表的副本来完成。但这就是为什么不应该这样做。在 100000 个随机整数的列表中,这在我的机器上需要 2500 毫秒:

       foreach (var x in listA.ToList())
if (x % 2 == 0)
listA.Remove(x);

这需要 1250 毫秒:

        for (int i = 0; i < listA.Count; i++)
if (listA[i] % 2 == 0)
listA.RemoveAt(i--);

而这两个分别需要 5 毫秒和 2 毫秒:

        listB = listB.Where(x => x % 2 != 0).ToList();

listB.RemoveAll(x => x % 2 == 0);

这是因为当你从列表中删除一个元素时,你实际上是从一个数组中删除,这是 O(N) 时间,因为你需要在 之后移动每个元素 删除的元素向左移动一位。平均而言,这将是 N/2 个元素。

Remove(element) 也需要在删除之前找到元素。所以 Remove(element) 实际上总是需要 N 步 - elementindex 步来找到元素,N - elementindex 步来删除它 - 总共 N 步。

RemoveAt(index) 不必找到元素,但它仍然需要移动底层数组,因此平均而言,RemoveAt 是 N/2 步。

无论哪种方式,最终结果都是 O(N^2) 复杂度,因为您要删除多达 N 个元素。

相反,您应该使用 Linq,它将在 O(N) 时间内修改整个列表,或者自己滚动,但您不应该在循环中使用 Remove(或 RemoveAt)。

关于c# - 在迭代列表时从列表中删除/添加项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17233558/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com