Python, but not programming, newbie here. I'm programming with lists and have run into an interesting problem.
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)
This results in the following output:
[(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)]
It completely skips the elements (2,1) and (1,2) -- without even checking them! I found answers here saying I shouldn't be modifying a list while traversing it, and yup, that definitely makes sense. Rookie mistake. But can someone tell me WHY it doesn't work? What's behind the veil of Python lists?
We can delete multiple elements from a list while iterating, but we need to make sure that we are not invalidating the iterator. So either we need to create a copy of the list for iteration and then delete elements from the original list, or we can use the list comprehension or filter() function to do the same.
The idea is to access the next element while iterating. On reaching the penultimate element, you can access the last element. Use enumerate method to add index or counter to an iterable(list, tuple, etc.). Now using the index+1, we can access the next element while iterating through the list.
In Python, use list methods clear() , pop() , and remove() to remove items (elements) from a list. It is also possible to delete items using del statement by specifying a position or range with an index or slice.
Others have explained that you should not remove elements from an array you are iterating over; however, if you traverse the array backwards, there is no problem.
The most compact way to solve this problem (assuming you don't need a copy of the original array after you are done) is to use the reversed()
function, as in
for square in reversed(squares)
This will start iterating from the end of the array, and work backwards. Taking out elements in this way will not affect the rest of the code, since you are not changing the order of elements you have not yet visited. I think this is the most elegant way to solve this. I learnt this trick here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With