tags:

views:

96

answers:

6

I have a list of lists that looks like:

floodfillque = [[1,1,e],[1,2,w], [1,3,e], [2,1,e], [2,2,e], [2,3,w]]

for each in floodfillque:
    if each[2] == 'w':
        floodfillque.remove(each)
    else:
        tempfloodfill.append(floodfillque[each[0+1][1]])

That is a simplified, but I think relevant part of the code.

Does the floodfillque[each[0+1]] part do what I think it is doing and taking the value at that location and adding one to it or no? The reason why I ask is I get this error:

TypeError: 'int' object is unsubscriptable

And I think I am misunderstanding what that code is actually doing or doing it wrong.

+3  A: 

Does the floodfillque[each[0+1] part do what I think it is doing and taking the value at that location and adding one to it or no?

No, it sounds like you want each[0] + 1.

Either way, the error you're getting is because you're trying to take the second item of an integer... each[0+1][1] resolves to each[1][1] which might be something like 3[1], which doesn't make any sense.

Joe Kington
I have a system in place to check to make sure that doesn't happen. But, maybe because I am modifying a list, that I am looping through that would cause this issue to occur?
NoahClark
+4  A: 

Here's what's happening:

On the first iteration of the loop, each is [1, 1, 'e']. Since each[2] != 'w', the else is executed.

In the else, you take each[0+1][1], which is the same as (each[0+1])[1]. each[0+1] is 1, and so you are doing (1)[1]. int objects can't be indexed, which is what's raising the error.

Aaron Gallagher
Okay, so then what is the solution? if I want each[0] + 1 can I do that?
NoahClark
The solution to what? I'm just pointing out why the exception is raised. Your question is too unclear to give any other kind of answer.
Aaron Gallagher
How can I add 1 to the list index, basically.
NoahClark
A: 

I don't really understand the question, but:

each[0+1] is exactly the same as each[1], simply because 0+1 is 1. So I think there is something wrong with each[0+1].

Michael
+3  A: 

The other posters are correct. However, there is another bug in this code, which is that you are modifying floodfillque as you are iterating over it. This will cause problems, because Python internally maintains a counter to handle the loop, and deleting elements does not modify the counter.

The safe way to do this is to iterate of a copy of the loop:

for each in floodfillque[ : ]:

([ : ] is Python's notation for a copy.)

katrielalex
+5  A: 

In addition to the bug in your code that other answers have already spotted, you have at least one more:

for each in floodfillque:
    if each[2] == 'w':
        floodfillque.remove(each)

don't add or remove items from the very container you're looping on. While such a bug will usually be diagnosed only for certain types of containers (not including lists), it's just as terrible for lists -- it will end up altering your intended semantics by skipping some items or seeing some items twice.

If you can't substantially alter and enhance your logic (generally by building a new, separate container rather than mucking with the one you're looping on), the simplest workaround is usually to loop on a copy of the container you must alter:

for each in list(floodfillque):

Now, your additions and removals won't alter what you're actually looping on (because what you're looping on is a copy, a "snapshot", made once and for all at loop's start) so your semantics will work as intended.

Your specific approach to altering floodfillque also has a performance bug -- it behaves quadratically, while sound logic (building a new container rather than altering the original one) would behave linearly. But, that bug is harder to fix without refactoring your code from the current not-so-nice logic to the new, well-founded one.

Alex Martelli
+1  A: 

Here is how I understand NoahClark's intentions:

  1. Remove those sublists whose third element is 'w'
  2. For the remaining sublist, add 1 to the second item

If this is the case, the following will do:

# Here is the original list
floodfillque = [[1,1,'e'], [1,2,'w'], [1,3,'e'], [2,1,'e'], [2,2,'e'], [2,3,'w']]

# Remove those sublists which have 'w' as the third element
# For the rest, add one to the second element
floodfillque = [[a,b+1,c] for a,b,c in floodfillque if c != 'w']

This solution works fine, but it is not the most efficient: it creates a new list instead of patching up the original one.

Hai Vu