I have a list
List1 = [(12,34),(12,6),(2,4),(1,3),(34,32),(34,6)]
and another list
List2 = [(12,34),(12,6),(2,4),(1,3),(34,32),(56,12),(78,23),(23,56)]
I want to create a new list, check the elements of the first against the elements of the second. Editing the second list basically. This list would become
List3 = [(56,12),(78,23),(23,56)]
If order/duplicates don't matter:
>>> A = [(12,34),(12,6),(2,4),(1,3),(34,32),(34,6)]
>>> B = [(12,34),(12,6),(2,4),(1,3),(34,32),(56,12),(78,23),(23,56)]
>>> set(B).difference(A)
set([(78, 23), (56, 12), (23, 56)])
Otherwise, if order does matter, just use a list comprehension check membership of a set (O(1) amortized membership checks):
>>> set_A = set(A)
>>> [x for x in B if x not in set_A]
[(56, 12), (78, 23), (23, 56)]
Keep in mind that this simple solution also works:
>>> [x for x in B if x not in A]
[(56, 12), (78, 23), (23, 56)]
It will just have to potentially scan through the entire list A every time it checks x not in A.
Related
I have a list of tuples, with each tuple containing a tuple pair, coordinates.
list1 = [((11, 11), (12, 12)), ((21, 21), (22, 22)), ((31, 31), (32, 32))]
Using list comprehension I am trying to generate a list without them being paired but still in the same order.
I was able to get the result be looping and using .append() but I was trying to avoid this.
new_list = []
for i in list1:
for x in i:
new_list.append(x)
print(new_list)
this works and gives me the result I am looking for:
[(11, 11), (12, 12), (21, 21), (22, 22), (31, 31), (32, 32)]
But when I try list comprehension I get the last tuple pair repeated!
new_list = [x for x in i for i in list1]
print(new_list)
[(31, 31), (31, 31), (31, 31), (32, 32), (32, 32), (32, 32)]
I am sure it is a small thing I am doing wrong so would appreciate the help!!
try :
print([inner_tuple for outer_tuple in list1 for inner_tuple in outer_tuple])
Nested fors should come to the right side. for sub in list1 after that for x in sub.
And btw, you didn't get NameError: name 'i' is not defined because, you wrote that list-comprehension after the for loop. In that time i is a global variable and exists.
The execution of the loop is out-inner type
Your code misses is close but it takes x only
Your code:
new_list = []
for i in list1:
for x in i:
new_list.append(x)
which is equivalent to
new_list = [x for i in list1 for x in i]
So, now you can understand the variables how they are taking values from for loops
I have two list of tuples,A and B, that stores the pairs of data ids, and I want to remove pairs from A if the pair (x,y) or (y,x) in B are also in A.
I tried to do it by using for loop like below,
A = [(321, 33), (56, 991), (645, 2), (8876, 556)]
B = [(33, 321), (645, 2)]
for pair in B:
if pair in A:
A.remove(pair)
elif (pair[1], pair[0]) in A:
A.remove((pair[1], pair[0]))
print(A) # [(56, 991), (8876, 556)]
but when the elements in list is large, this code runs very slowly.
So I want to make this code faster, possibly avoid using for loops or completely different way.
Can someone help me to solve this problem?
If A has unique items, you can convert both lists to sets and use set difference, with the caveat that you add the reversed tuples into the B_set:
set_B = set(B).union([(j,i) for (i,j) in B])
out = list(set(A) - set_B)
Output:
[(321, 33), (645, 2)]
If A doesn't have unique items and you want to keep duplicate items, you can use list comprehension for the second line instead:
set_B = set(B).union([(j,i) for (i,j) in B])
out = [tpl for tpl in A if tpl in set_B]
Provided that you use sets instead of lists and that the second set contains both variants of elements ((x, y) and (x, y))…
A = {(321, 33), (56, 991), (645, 2), (8876, 556)}
B = {(33, 321), (645, 2), (321, 33), (2, 645)}
You only need a set subtraction:
print(A - B)
Instead of removing, create a new list by excluding the common elements:
[(x,y) for x,y in A if (x,y) not in B and (y,x) not in B]
Output:
[(56, 991), (8876, 556)]
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.
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)}
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)
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)]
I am trying to find duplicates within tuples that are nested within a list. This whole construction is a list too. If there are other better ways to organize this to let my problem to be solved - I'd be glad to know, because this is something I build on the way.
pairsList = [
[1, (11, 12), (13, 14)], #list1
[2, (21, 22), (23, 24)], #list2
[3, (31, 32), (13, 14)], #list3
[4, (43, 44), (21, 22)], #list4
]
The first element in each list uniquely identifies each list.
From this object pairsList, I want to find out which lists have identical tuples. So I want to report that list1 has the same tuple as list3 (because both have (13,14). Likewise, list2 and list4 have the same tuple (both have (21,22)) and need to be reported. The position of tuples within the list doesn't matter (list2 and list4 both have (13,14) even though the position in the list the tuple has is different).
The output result could be anything iterable later on such as (1,3),(2,4) or [1,3],[2,4]. It is the pairs I am interested in.
I am aware of sets and have used them to delete duplicates within the lists in other situations, but cannot understand how to solve this problem. I can check like this if one list contains any element from the other list:
list1 = [1, (11, 12), (13, 14)]
list2 = [3, (31, 32), (13, 14)]
print not set(list1).isdisjoint(list2)
>>>True
So, the code below lets me know what lists have same tuple(s) as the first one. But what is the correct way to perform this on all the lists?
counter = 0
for pair in pairsList:
list0 = pairsList[0]
iterList = pairsList[counter]
if not set(list0).isdisjoint(iterList):
print iterList[0] #print list ID
counter += 1
The first element in each list uniquely identifies each list.
Great, then let's convert it to a dict first:
d = {x[0]: x[1:] for x in pairsList}
# d:
{1: [(11, 12), (13, 14)],
2: [(21, 22), (23, 24)],
3: [(31, 32), (13, 14)],
4: [(43, 44), (21, 22)]}
Let's index the whole data structure:
index = {}
for k, vv in d.iteritems():
for v in vv:
index.setdefault(v, []).append(k)
Now index is:
{(11, 12): [1],
(13, 14): [1, 3],
(21, 22): [2, 4],
(23, 24): [2],
(31, 32): [3],
(43, 44): [4]}
The output result could be anything iterable later on such as (1,3),(2,4) or [1,3],[2,4]. It is the pairs I am interested in.
pairs = [v for v in index.itervalues() if len(v) == 2]
returns [[1,3],[2,4]].
Say I have a list:
[(12,34,1),(123,34,1),(21,23,1)]
I want to remove the 1 from each tuple in the list so it becomes
[(12,34),(123,34),(21,23)]
You want to truncate your tuples, use a list comprehension:
[t[:-1] for t in listoftuples]
or, as a simple demonstration:
>>> listoftuples = [(12,34,1),(123,34,1),(21,23,1)]
>>> [t[:-1] for t in listoftuples]
[(12, 34), (123, 34), (21, 23)]
Tuples are immutable, so you can not remove an item. However, you can create a new tuple from the old tuple not including the elements you do not want to. So, to delete an arbitrary item from each tuple from a list of tuples, you can do:
def deleteItem(lst, toDel):
return [tuple(x for x in y if x != toDel) for y in lst]
Result:
>>> lst = [(12,34,1),(123,34,1),(21,23,1)]
>>> deleteItem(lst, 1)
[(12, 34), (123, 34), (21, 23)]
>>> a=[(12, 34, 1), (123, 34, 1), (21, 23, 1)]
>>> [filter (lambda a: a != 1, x) for x in a]
[(12, 34), (123, 34), (21, 23)]
THis will remove all 1 from the tuple irrespective of index
Since you can't change tuples (as they are immutable), I suggest using a list of lists:
my_list = [[12,34,1],[123,34,1],[21,23,1]]
for i in my_list:
i.remove(1)
return my_list
This returns: [[12, 34], [123, 34], [21, 21]].
python 3.2
1. [(i,v)for i,v,c in list1]
2. list(map(lambda x:x[:2],list1))