0

I have two sequences that I want to put into a list of (x, y) coordinates.

seq1 = "11-345"
seq2 = "122--5"

I want to remove any (x, y) pair that contains a '-' so I wrote a simple for loop, but it doesn't remove all of the pairs. If there are multiple '-'s next to each other, some are not removed.

z = zip(seq1, seq2)
for (x, y) in z:
    if x == '-' or y == '-':
        z.remove((x, y))

In this example, it gives me z = [('1', '1'), ('1', '2'), ('3', '-'), ('5', '5')] Sometimes only the first is removed, sometimes the last, depending on the sequence. Any ideas as to why or how to fix this?

Katie J
  • 77
  • 1
  • 1
  • 8
  • 4
    Modifying a list while iterating over it is a really bad move. Try `z = [(x, y) for x, y in zip(seq1, seq2) if x != '-' and y != '-']` (and see https://docs.python.org/2/tutorial/datastructures.html#list-comprehensions) – jonrsharpe Aug 07 '15 at 15:32
  • Cool, that works great. Thanks! – Katie J Aug 07 '15 at 15:36
  • 2
    @VincentLaufer what on earth are you doing? – jonrsharpe Aug 07 '15 at 15:42
  • @KatieJ: I assume your desired result for the given input data is `[('1', '1'), ('1', '2'), ('5', '5')]`. You should mention that explicitly in your question. – PM 2Ring Aug 07 '15 at 15:47

3 Answers3

1

To increase performance, you can use both list comprehension and an iterator instead of a list of tuples

from itertools import izip
z = [ (x, y) for x, y in izip(seq1, seq2) if x != "-" and y != "-" ]
wpercy
  • 9,636
  • 4
  • 33
  • 45
1

You miss one because you're modifying the list in the middle of iterating over it. The iterator moves from index 2 to index 3 just as you delete index 2, moving the element at 3 into position 2, which you just passed. If you print as you go, you can see it skip (3, '-') and (5, 5) because you delete the element directly before them:

for (x,y) in z:
  print(x, y)
  if x == '-' or y == '-':
    z.remove((x, y))

('1', '1')
('1', '2')
('-', '2')
('4', '-')

Using list comprehension to create a new list instead avoids the problem.

for z in [(x, y) for x, y in zip(seq1, seq2) if x != '-' and y != '-']:
  print z

('1', '1')
('1', '2')
('5', '5')
Kristján
  • 18,165
  • 5
  • 50
  • 62
0

You use the slice notation that creates a copy of the whole array:

seq1 = "11-345"
seq2 = "122--5"

z = zip(seq1, seq2)
for (x, y) in z[:]:
    if x == '-' or y == '-':
        z.remove((x, y))
Freelancer
  • 4,459
  • 2
  • 22
  • 28