Python,但不是编程,新手在这里。我正在使用列表进行编程,并遇到了一个有趣的问题。
width = 2
height = 2
# Traverse the board
def traverse(x, y):
# The four possible directions
squares = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]
print squares
# Remove impossible squares
for square in squares:
print "now accessing", square
if (square[0] < 1 or square[0] > width or
square[1] < 1 or square[1] > height or
square == (1, height)):
squares.remove(square)
print "removed", square
print(squares)
# Testing traverse
traverse(1,1)
这导致以下输出:
[(0, 1), (2, 1), (1, 0), (1, 2)]
now accessing (0, 1)
removed (0, 1)
now accessing (1, 0)
removed (1, 0)
[(2, 1), (1, 2)]
它完全跳过元素(2,1)和(1,2) - 甚至没有检查它们!我在这里找到了答案,说我不应该在遍历它时修改列表,并且是的,这绝对有意义。菜鸟错了。但有人可以告诉我为什么它不起作用? Python列表背后隐藏着什么?
答案 0 :(得分:14)
语句for square in squares
只是按顺序访问列表中的每个项目:squares[0]
,然后是squares[1]
,然后是squares[2]
,依此类推,直到广告用完为止。
删除squares[0]
会将列表中的所有其他项目移至左侧一个广告位;原始squares[1]
现在是squares[0]
,因此for循环将跳过它。
答案 1 :(得分:9)
其他人已经解释过你不应该从正在迭代的数组中删除元素;但是,如果向后遍历数组,则没有问题。
解决此问题的最紧凑方法(假设您在完成后不需要原始数组的副本)是使用reversed()
函数,如
for square in reversed(squares)
这将从数组的末尾开始迭代,然后向后工作。以这种方式取出元素不会影响代码的其余部分,因为您不会更改尚未访问的元素的顺序。我认为这是解决这个问题最优雅的方法。我学会了这个技巧here
答案 2 :(得分:1)
您正在迭代它时从列表中删除。这不是一个好主意 还有其他方法可以执行您正在尝试的操作,其中一种方法是跟踪要从列表中删除的所有项目的列表索引,然后将其从for-loop中删除
答案 3 :(得分:0)
当您在Python中访问列表并删除元素时,列表会变短。
简单示例:取列表1,2,3,4,5,并删除素数&gt; 1.
如果你看第二个元素(2)并决定删除它,你最终会得到一个1,3,4,5的列表
现在你看第三个元素(你已经看过第二个元素了),你发现它是4.那不是素数,所以你去第五个元素 - 5.删除它。
结果:你有1,3,4,5。
如果你是从数组的另一端开始的,那么事情就可以了。
有意义吗?
编辑: 我在下面创建了另一个答案 - 其他海报对问题的解释比我在这里给出的更好,但我认为我有一个更优雅的解决方案。
答案 4 :(得分:0)
不建议在for循环中删除数组元素,因为for循环按顺序检查索引,而在循环中删除元素则将进行中的元素向左移一个索引,如果要这样做,则使用reversed()
arr = [1,2,3,4,5]
对于ele反向(arr): 健康)状况: arr.remove(ele)
答案 5 :(得分:-1)
不要修改您正在迭代的列表!
相反,做一些事情:
for square in squares[:]:
这样你就可以在更改原始内容的同时迭代列表的副本。