4

while i'm interating a list, how can i get the id of the current item to reference it to list methods?

xl = [1,2,3] # initial list
yl = [3,2]   # list used to remove items from initial list

for x in xl[:]:
    for y in yl:
        if x == y:
            xl.pop(x) # problem
            break
        print x, y
print xl

in the simple example, i want to loop through the 2 lists, and when i find a similar item, remove it from list 1.

What should i use instead of X in the line commented with "#problem"?

PS: Note it's a copy i'm iterating from.

3 Answers 3

8

The general way to do this is with enumerate.

for idx, item in enumerate(iterable):
  pass

But for your use case, this is not very pythonic way to do what you seem to be trying. Iterating over a list and modifying it at the same time should be avoided. Just use a list comprehension:

xl = [item for item in xl if item not in yl]
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for enumerate but to clarify, its ok to modify a list while looping in terms of changing the value of indexes but not the size of the list. Though doing it over a copy is safe though maybe not efficient.
4

How about xl = [x for x in xl if x not in y]

This is known as a list comprehension.

5 Comments

it was a 'simple example'. it will require http requests and what not to make the check, not just matching two numbers.
@gcb That's not a problem. You can check as much as you want, with xl = [x for x in xl if checkHttpRequestsAndWhatNot(x)], or shorter x1 = filter(x1, checkHttpRequestsAndWhatNot).
that's a good point... think i will review the structures i'm using right now.
It sounds as if you didn't really ask the question that you wanted answered. You might update the question to make it more precise. When you ask a simple question, you'll often find there is a simple answer available.
the answer about enumerate answered the question just right, but you and phihag raised a good point about using list comprehension and a bunch of functions instead of a flag and a bunch of loops. but it's sideways to the question, i think
2

Instead of removing elements you don't like, you should simply use filter:

x1 = filter(x1, lambda x: x not in y1)

Alternatively, a list comprehension works as well:

x1 = [x for x in x1 if x not in y1]

If y1 is very large, you should look up in a set, like this:

y1set = set(y1)
x1 = filter(x1, lambda x: x not in y1set)

For reference, pop takes an index, and the generic way to get an index is enumerate. However, in nearly all cases, there's a shorter and cleaner way to write the code than using indices.

7 Comments

this is really a mapping to a database. so in this case i want to keep the indexes. in my business logic, when i remove from the DB, i will remove from the in memory list. think i will end up using explicity indexes matching the DB...
@gcb If you want to keep the indices, you shouldn't be using pop, but setting the entries in the x1 list to some marker value such as None.
i want to drop the indexes too.
@gcb Well, then simply use filter. Sorry, but I don't understand why you desperately want to call pop. pop is extremely slow by design, since it needs to copy a large part of the list and potentially reallocate the list afterwards.
i'm using it as sort of queue, so it may be slower, but it's the best analogy to not make the code too esoteric when i read it later :) but i may review that to use list comprehension instead of a queue.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.