I want to remove the tuple from the list whose first elements are the same since I am treating the letter pairs as having the same value despite their ordering. Here is the list I am trying to iterate through, called tuples2
:
[(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')]
My current code:
for i in list(tuples2):
if i[0] == i+1[0]:
tuples2.remove(i)
print tuples2
...Is throwing this error:
line 6: if i[0] == (i+1)[0]: TypeError: can only concatenate tuple (not "int") to tuple
How should I modify my code to account for this if I wanted to end up with
[(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]
?
You can loop through the list items by using a while loop. Use the len() function to determine the length of the tuple, then start at 0 and loop your way through the tuple items by refering to their indexes. Remember to increase the index by 1 after each iteration.
Easiest way is to employ two nested for loops. Outer loop fetches each tuple and inner loop traverses each item from the tuple. Inner print() function end=' ' to print all items in a tuple in one line. Another print() introduces new line after each tuple.
Solution: To iterate over a Python list lst in pairs, iterate over all list indices i from 0 to the index of the second last list element (included). In the loop body, use the indices to retrieve the windows by slicing lst[i:i+2] .
There are a lot of red-flags in this code. You should not be modifying a list that you are iterating over, that will cause you stop skip over items. EDIT I now see that you copied the list in your for-loop, but still, the following approach is a bit more safe. You can iterate backwards, but it's probably easier to build a new list. A straightforward way is to keep track of already-seen first elements, and only add if you haven't seen the first element before:
In [1]: data = [(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')]
...:
In [2]: seen = set()
In [3]: new_data = []
...: for triple in data:
...: first = triple[0]
...: if first in seen:
...: continue
...: seen.add(first)
...: new_data.append(triple)
...:
In [4]: new_data
Out[4]: [(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]
Using .remove
is very inefficient. It changes your algorithm into O(n^2) rather than O(n).
You could read into a dictionary keyed by the first components and then read out the values:
tuples = [(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')]
d = {x:(x,y,z) for x,y,z in tuples}
tuples = list(d.values())
Resulting tuples
:
[(1, 'B', 'A'), (2, 'C', 'B'), (3, 'C', 'A')]
You have a false concept of the iteration of i in list(tuples2)
: Using this syntax, i is not a index but actually the tuple itself. So, you can't do i+1[0]
.
First, I recommend you do:
tuples_list = list(tuples2)
To solve this, you can use the xrange
that python suggests (or range
) that will work by index:
for i in xrange(len(tuples_list)-1):
if tuples_list[i][0] == tuples_list[i+1][0]:
#Do what you want
Just group by first element and take the first of each group.
>>> [next(g) for _, g in itertools.groupby(tuples2, lambda x: x[0])]
[(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]
Or even simpler:
>>> tuples2[::2]
[(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With