删除List 中的备用元素

在不使用占位符列表变量的情况下,在List删除备用(奇数索引或甚至索引)元素的最有效方法是什么?

如果您能提出每个答案的费用,我们将不胜感激。

我正在寻找一种有效的方法来做到这一点

提前致谢

如果您为删除的每个项目调用RemoveAt,您将移动大量数据。 最有效的方法是将要保留的项目移动到一起,然后在最后删除未使用的项目:

 int pos = 0; for (int i = 0; i < values.Count; i += 2, pos++) { values[pos] = values[i]; } values.RemoveRange(pos, values.Count - pos); 

编辑:
此方法将在15毫秒内处理一百万个整数的列表。 使用RemoveAt将需要三分钟......

EDIT2:
实际上你可以从pos = 1和i = 2(或3)开始,因为第一项不必复制到自身。 这使得代码不那么明显了。

只是为了考虑创建新列表的解决方案,使用旧列表,您可以执行以下操作:

 var newList = old.Where((_, i) => i%2 != 0).ToList(); 

或者,显然

 var newList = l.Where((_, i) => i%2 == 0).ToList(); 

取决于您选择的替换。

编辑

答案要快得多。 如果你在这里读到别的东西,那是因为我在周末和周末测量的大脑很有趣。 :(关闭解决方案大约快40%,而答案是应用程序快2个数量级。我想这将取决于您的列表有多大!

另一种选择,类似于弗兰克的选择,但使用了闭包。 它比弗兰克的版本更快。

 bool isEven = true; var newList = list.Where(x => isEven = !isEven).ToList(); 

我不确定你的意思是替代,但如果你的意思是“每隔一个项目”,下面的代码将起作用。 它将从删除第二个元素开始,然后是第四个元素,依此类推

 List list = GetTheList(); int i = 1; while ( i < list.Count ) { list.RemoveAt(i); i++; } 

Nirvana的方式是延迟执行。 或者其他的东西。

  public static IEnumerable AlternateItems(this IEnumerable source) { while (source.Any()) { yield return source.First(); source = source.Skip(1); if (source.Any()) source = source.Skip(1); } } 

这适用于所有序列,而不仅仅是IList<> 。 迭代的成本推迟到迭代,如果最终您不需要触摸列表中的所有元素,这可能是一个巨大的胜利。

在我的简单测试中,当您遍历整个列表时的性能不是很好,所以一定要描述您的实际情况。

 for (int i=myList.length-1; i >= 0; i--) if (i % 2 == 0) myList.Remove(myList[i]); 

显然使用依赖,但你可以有一个包装器IList,它将你给它的索引乘以2,并将列表的长度报告为1/2(细节省略)。 这是O(1)。

我会使用通常用于STL容器的标准模式。 删除后删除。

通过这种方式,您不会混淆习惯于看到此模式的人。

 template struct RemoveEven { RemoveEven():count(0) {} bool operator()(T const&) { bool result = count%2 == 0; count++; return result; } private: std::size_t count; }; int main() { std::list a; a.erase(std::remove_if(a.begin(),a.end(),RemoveEven()),a.end()); }