我想通过迭代并检查它是否满足某些要求来从python列表中删除特定项。首先,我只是操作一个自定义类对象的列表,但它实际上遇到了一些错误,我在一个原始类型int的python列表上进行实验,只是为了找到奇怪的结果!
以下是一些代码摘录:
n=size of nodes
我希望循环后// nodes and selectionSize are my input:
int[] nodes = {1,2,3...,1000}; // 1000 elements
int selectionSize = 500; // This can be at most the size of the elements (in this case 1000)
run_algo(nodes, selectionSize);
public void run_algo(int[] nodes, int selectionSize) {
randomNodesList = {};
while(randomNodesList < selectionSize) {
randomNode = selectRandomNode(nodes); // Assume O(1)
if(!randomNodesList.exists(randomNode)) { // Assume O(1)
randomNodesList.push_back(randomNode); // Assume O(1)
}
}
foreach(node in randomNodesList) {
foreach(neighbor in node.getNeighbors()) { // Max. nodes size (in this case 1000)
if (!randomNodesList.exists(neighbor)) { // Assume O(1)
AddEdge(node, neighbor); // Takes O(1) time
}
}
}
}
应为>>> a=[1,2,3,4,5]
>>> for i in a:
... a.remove(i)
...
>>> a
[2, 4]
,但事实证明它是a
,我想知道为什么。我在Remove items from a list while iterating中找到了一个相关问题,但它只提供了如何删除特定项目的解决方案,而不是实际上与机制有关。我真的想知道这个奇怪结果的原因。
答案 0 :(得分:0)
让我们尝试打印i和a迭代的值。
for i in a:
print i, a
a.remove(i)
输出将是:
1 [1, 2, 3, 4, 5]
3 [2, 3, 4, 5]
5 [2, 4, 5]
所以当你删除一个元素时,索引会改变,所以当索引1的值早于2时,现在它是3.这将是i的值。
答案 1 :(得分:0)
所以你已经暴露了一些python实现。基本上,一个数组为python列表提供支持,它只是将数组索引递增1.因此它将转到a[0]
,a[1]
,a[2]
...并检查在每次迭代之前,它不会从数组的末尾运行。当您删除第一项&#39; 1&#39;从列表中,&#39; 2&#39;移至a[0]
。该数组现在看起来像[2,3,4,5]
。迭代器现在指向a[1]
,所以现在&#39; 3&#39;被删除。最后,跳过&#39; 4&#39; 5&#39; 5&#39;被删除。
a = [1,2,3,4,5]
for i in a:
print("a:%s i=%s"%(a,i))
a.remove(i)
print("final a: %s"%a)
提供输出
a:[1, 2, 3, 4, 5] i=1
a:[2, 3, 4, 5] i=3
a:[2, 4, 5] i=5
final a: [2, 4]
如果你感兴趣,这里有真正的基本要点。 https://github.com/python/cpython/blob/master/Objects/listobject.c#L2832
答案 2 :(得分:-1)
您的解决方案无法按预期工作的原因是因为迭代器的行为方式与您在修改列表时所期望的方式不同。如果您的示例以这种方式重写,您将获得您期望的结果。
>>> a=[1,2,3,4,5]
>>> b = a[:]
>>> for i in b:
... a.remove(i)
...
>>> a
[]
这是因为&#39; b&#39;是一个&#39; a&#39;的副本,因此当a执行时不会被修改。这意味着迭代器没有在其下修改数据结构。
更有效的解决方案是:
a = [1,2,3,4,5]
a = [i for i in a if not condition(i)]
此列表理解在通过源列表时会复制,并且只会复制未被删除的元素。