Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate through a list of tuples containing three pair values?

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')]?

like image 621
Cora Coleman Avatar asked Mar 04 '17 00:03

Cora Coleman


People also ask

Can you iterate through a list of tuples?

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.

How do you loop through a tuple of tuples?

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.

How do you iterate through a pair in a list Python?

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] .


4 Answers

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).

like image 140
juanpa.arrivillaga Avatar answered Oct 21 '22 13:10

juanpa.arrivillaga


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')]
like image 33
John Coleman Avatar answered Oct 21 '22 13:10

John Coleman


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
like image 3
Ofer Arial Avatar answered Oct 21 '22 14:10

Ofer Arial


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')]
like image 2
Stefan Pochmann Avatar answered Oct 21 '22 14:10

Stefan Pochmann