0

I have a list of tuples that starts out empty and is appended with new user-generated tuples.

if left_mouse == True:
    generic_list.append((mouse_position_x, mouse_position_y))

To prevent having multiple tuples with the same (x, y) data, I want to iterate through the list and check if the newest tuple is the same as any other tuple in the list, and if it is, replace the old tuple with the new one.

for tuple in tuple_list:
    if tuple_list[-1].position == tuple_list[i].position:
         tuple_list.remove(i)

I know what I've got is wrong, but I don't know why or how to move forward. Any help would be really appreciated.

Edit: I'm now using set() and it works perfectly. Thanks everyone.

MaxG
  • 65
  • 3
  • 3
    You're iterating through the list at the same time as you are modifying it. – univerio Mar 07 '16 at 22:39
  • 3
    why do you want to replace it with the same? Actually hang on, why are you adding it at all instead of checking if it an equal tuple is in the list before adding? – Padraic Cunningham Mar 07 '16 at 22:39
  • As univerio said, removing items from a list you're iterating over is a bad idea. This question shows why: [strange result when removing item from a list](http://stackoverflow.com/q/6260089/4014959). Also, removing items from inside a list is an expensive operation because all subsequent items have to be moved down. BTW, you shouldn't use `tuple` as a variable name as it shadows the built-in `tuple` type. – PM 2Ring Mar 07 '16 at 22:49
  • 1
    Also what is `i` supposed to be? – Padraic Cunningham Mar 07 '16 at 22:51

3 Answers3

0

If order doesn't matter, you could use a set. It'll keep only unique tuple in your list. Then you can create a new list from this set if needed. For example:

generic_list = [(1,2), (3,4), (1,2), (5,6)]
generic_list = set(generic_list)  # {(1, 2), (3, 4), (5, 6)}
generic_list = list(generic_list) # [(1, 2), (5, 6), (3, 4)]
pie
  • 365
  • 2
  • 9
0

i recommend using a set (instead of a list):

>>> d = {tuple(RND.sample(range(100), 2)) for c in range(5)}
>>> d
{(17, 53), (74, 5), (88, 11), (21, 56), (15, 78)}
>>> type(d)
<class 'set'>

>>> a = (15, 78)
>>> a in d
True
>>> b = (32, 6)
>>> b in d
False
>>> d.add((4, 1))
>>> d
{(74, 5), (15, 78), (17, 53), (88, 11), (4, 1), (21, 56)}
doug
  • 69,080
  • 24
  • 165
  • 199
0

To your specific question: You are iterating over your tuple_list with a variable called tuple. That's what you should use to compare against:

last_tuple = tuple_list[-1]
for tuple in tuple_list[:-1]:
    if tuple.position == last_tuple.position:
        tuple_list.remove(tuple)

Except you should not do that at all, because you're doing all kinds of extra work. Instead, maintain a set in parallel with your tuple list, and use the set to determine whether you have seen the position before. (This assumes your list is hundreds or thousands of elements long. If you're only tracking three or four positions, you could just lsearch the list.)

generic_list = []
positions_seen = set(generic_list)

# blah blah blah code

if left_mouse:
    pos = (mouse_position_x, mouse_position_y)
    if pos not in positions_seen:
        positions_seen.add(pos)
        generic_list.append(pos)
aghast
  • 14,785
  • 3
  • 24
  • 56