Nice Chang
Nice Chang

Reputation: 137

Why I can't remove some value in list?

matched_edges = [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
process = matched_edges
print(process)

for tup in matched_edges:
    if (tup[1], tup[0]) in process:
        process.remove((tup[1], tup[0]))
    if -1 in tup:
        process.remove(tup)
        print(tup)
print(process)

[(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
(0, -1)
[(1, -1), (2, 3), (4, 6), (5, 7), (8, 9)]

I tried many ways, but I just can't remove (1,-1).What's wrong?

-1 in (1, -1)

True

Upvotes: 1

Views: 74

Answers (6)

Vignesh G
Vignesh G

Reputation: 149

The following works fine for me.

matched_edges = [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), 
                (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]

process = []

for tup in matched_edges:
    if (tup[0] != -1 and tup[1] != -1) and (tup[1], tup[0]) not in process:
        process.append(tup)
print(process)

Output

[(2, 3), (4, 6), (5, 7), (8, 9)]

Upvotes: 0

Giovanni Rescia
Giovanni Rescia

Reputation: 590

The problem is that you do process = matched_edges, you are creating a variable (process) that points to the same object as matched_edges, to create a new list with the same values you should do process = matched_edges[:] instead.

So your code would look like:

matched_edges = [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
process = matched_edges[:]
print(process)

for tup in matched_edges:
    if (tup[1], tup[0]) in process:
        process.remove((tup[1], tup[0]))
    if -1 in tup:
        process.remove(tup)
        print(tup)
print(process)

Upvotes: 0

Aelarion
Aelarion

Reputation: 417

This line process = matched_edges is actually creating a reference to the matched_edges list, not a copy of the items. In turn, this is affecting your iterator in the for loop as you remove items from process (and matched_edges). To demonstrate I slightly modified your code (just to print values):

matched_edges = [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
process = matched_edges

for tup in matched_edges:
    print(f"Current tup: {tup}")
    print(f"Process: {process}")
    print(f"Matched: {matched_edges}")
    if (tup[1], tup[0]) in process:
        process.remove((tup[1], tup[0]))
    if -1 in tup:
        process.remove(tup)

Output:

Current tup: (0, -1)
Process: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (2, 3)
Process: [(1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Matched: [(1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (4, 6)
Process: [(1, -1), (2, 3), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Matched: [(1, -1), (2, 3), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (5, 7)
Process: [(1, -1), (2, 3), (4, 6), (5, 7), (7, 5), (8, 9), (9, 8)]
Matched: [(1, -1), (2, 3), (4, 6), (5, 7), (7, 5), (8, 9), (9, 8)]
Current tup: (8, 9)
Process: [(1, -1), (2, 3), (4, 6), (5, 7), (8, 9), (9, 8)]
Matched: [(1, -1), (2, 3), (4, 6), (5, 7), (8, 9), (9, 8)]

You can see on the second iteration you end up skipping the (1, -1) tuple. In general, you're skipping an item every time you remove one.

Change your assignment to process to use copy() so you get a new list:

process = matched_edges.copy()

This should fix the odd behavior. Although I'm not quite sure if the loop you're using still does exactly what you intend it to, but this is the output with the copied list:

Current tup: (0, -1)
Process: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (1, -1)
Process: [(1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (2, 3)
Process: [(2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (3, 2)
Process: [(2, 3), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (4, 6)
Process: [(4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (5, 7)
Process: [(4, 6), (5, 7), (7, 5), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (6, 4)
Process: [(4, 6), (5, 7), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (7, 5)
Process: [(5, 7), (8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (8, 9)
Process: [(8, 9), (9, 8)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
Current tup: (9, 8)
Process: [(8, 9)]
Matched: [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]

Upvotes: 1

Moon President
Moon President

Reputation: 98

Have you tried something like

process = [tup for tup in matched_edges if (tup[0] != -1 and tup[1] != -1)]

That should remove any tuple with -1 in it.

Edit

Also, the reason the code is behaving strangely is that matched_edges and process both hold the same object, so as you remove objects from process you are also removing them from matched_edges during iteration, resulting in unexpected bahaviour. Run the following code and you will see what I mean.

matched_edges = [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
process = matched_edges
print(process)

for tup in matched_edges:
    print(tup)
    print("Length of matched edges:", len(matched_edges))
    if (tup[1], tup[0]) in process:
        process.remove((tup[1], tup[0]))
    if -1 in tup:
        process.remove(tup)
        print("removing", tup)
print(process)

matched_edges = [tup for tup in matched_edges if (tup[0] != -1 and tup[1] != -1)]
print(matched_edges)

Upvotes: 0

Niel Godfrey P. Ponciano
Niel Godfrey P. Ponciano

Reputation: 10719

This is the incorrect line

process = matched_edges

Here is a programming rule. As much as possible, do not update the object you are currently iterating on! What was done in your code is that process and matched_edges points/refers to the same object/list in heap memory (different stack variables but both pointing to the same memory address in heap which is the actual list) thus updating process means you are also indirectly updating matched_edges.

You are currently iterating matched_edges:

for tup in matched_edges:

Then, you updated process, which messed up your iteration of matched_edges:

process.remove(...)

The correction to your code is to use this instead:

process = matched_edges.copy()

Upvotes: 3

Buddy Bob
Buddy Bob

Reputation: 5889

You could just create a new list.

matched_edges = [(0, -1), (1, -1), (2, 3), (3, 2), (4, 6), (5, 7), (6, 4), (7, 5), (8, 9), (9, 8)]
process = []
for tup in matched_edges:
    if (tup[1], tup[0]) in matched_edges:matched_edges.remove((tup[1], tup[0]))
    if -1 not in tup:process.append(tup)
print(process)

output

[(2, 3), (4, 6), (5, 7), (8, 9)]

Upvotes: 0

Related Questions