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

I want to remove a tuple from the list whose first elements are the same, since I treat the pairs of letters as having the same value, despite their ordering. Here is the list I'm trying to tuples2 through, called tuples2 :

 [(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')] 

My current code is:

 for i in list(tuples2): if i[0] == i+1[0]: tuples2.remove(i) print tuples2 

... Throws this error:

 line 6: if i[0] == (i+1)[0]: TypeError: can only concatenate tuple (not "int") to tuple 

How can I change my code to this account if I want to end with [(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')] ?

+5
source share
6 answers

There are a lot of red flags in this code. You should not change the list that you repeat, which will cause you to stop skipping items. EDIT Now I see that you have copied the list in your for-loop, but, nevertheless, the following approach is safer. You can iterate over backwards, but it's probably easier to create a new list. The direct way is to track the first elements already seen and add only if you have not 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 very inefficient. It changes your algorithm to O (n ^ 2), not O (n).

+4
source

You have a false concept of iteration i in list(tuples2) : using this syntax, I am not an index, but the tuple itself. Thus, you cannot do i+1[0] .

First I recommend you:

 tuples_list = list(tuples2) 

To solve this problem, you can use xrange , which offers python (or range ), which 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 
+3
source

You can read the dictionary referenced by the first components, and then read 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()) 

Result of tuples :

 [(1, 'B', 'A'), (2, 'C', 'B'), (3, 'C', 'A')] 
+3
source

You can solve your question using groupby from the itertools module as follows:

 from itertools import groubpy a = [(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'B', 'A')] final = [list(v)[0] for _,v in groupby(sorted(a), lambda x: x[0])] print(final) 

Output:

 >>> [(1, 'A', 'B'), (2, 'B', 'C'), (3, 'A', 'C')] 

Otherwise, if you need the final list in the same order that you specified in your question, you can cancel it:

 final = list(reversed(final)) # OR #final = sorted(final, reverse = True) print(final) 

Output:

 >>> [(3, 'A', 'C'), (2, 'B', 'C'), (1, 'A', 'B')] 
+2
source

Just group by the 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')] 
+2
source

IMMEDIATE PROBLEM

What does this mean?

 i+1[0] 

i is the tuple; you are trying to use i as an index and an element. The iteration you need is more like:

 for i in range (len(tuples2)): if tuples2[i] == tuples2[i+1]: 

... who is still not doing this job. This checks the equality of the entire tuple. However, you say that all you care about is the equality of the first element. Then you need to:

  if tuples2[i][0] == tuples2[i+1][0]: 

This is in terms of your current code; others have shown you more β€œpythonic” ways to do this.

COMMON DECISION

This code assumes that the other elements of the tuple are equal, with tuples with the same first elements adjacent in the list, and that matching tuples fall only in pairs. Is it possible that your list will include the following:

 tuples2 = [(3, 'A', 'C'), (3, 'C', 'A'), (2, 'B', 'C'), (2, 'C', 'B'), (1, 'A', 'B'), (1, 'A', 'Z'), (1, 'B', 'A')] 

With an additional β€œZ” element, possibly buried between the β€œ3” elements? Despite this, even if you sort the list, you get the "AZ" element between the other "1" elements.

If this is a problem for you, I suggest converting each tuple to a list first, sorting the elements in order. For example, you had to convert (1, 'B', 'A') to [1, 'A', 'B']. Then use any of these methods to eliminate duplicates, including the one you have already programmed. I usually do this by turning things back into tuples and then forming a set that automatically removes duplicates.

+1
source

Source: https://habr.com/ru/post/1265012/


All Articles