Removing duplicates from tuples within a list - python

I have a list of tuples:
lst = [('a','b'), ('c', 'b'), ('a', 'd'), ('e','f'), ('a', 'b')]
I want the following output list:
output = [('a','b'), ('e','f')]
i.e I want to compare the elements of first tuple with remaining tuples and remove the tuple which contains either one or more duplicate elements.
My attempt:
I was thinking of using for loops, but that wont be feasible once i have very large list. I browsed through following posts but could not get the right solution:
Removing duplicates members from a list of tuples
How do you remove duplicates from a list in whilst preserving order?
If somebody could guide me the right direction, it will be very helpful. Thanks!

Assuming that you want "duplicates" of all elements to be suppressed, and not just the first one, you could use:
lst = [('a','b'), ('c', 'b'), ('a', 'd'), ('e','f'), ('a', 'b')]
def merge(x):
s = set()
for i in x:
if not s.intersection(i):
yield i
s.update(i)
gives
>>> list(merge(lst))
[('a', 'b'), ('e', 'f')]
>>> list(merge([('a', 'b'), ('c', 'd'), ('c', 'e')]))
[('a', 'b'), ('c', 'd')]
>>> list(merge([('a', 'b'), ('a', 'c'), ('c', 'd')]))
[('a', 'b'), ('c', 'd')]

Sets should help:
>>> s = map(set, lst)
>>> first = s[0]
>>> [first] + [i for i in s if not i & first]
[set(['a', 'b']), set(['e', 'f'])]
Or with ifilterfalse:
>>> from itertools import ifilterfalse
>>> s = map(set, lst)
>>> [first] + list(ifilterfalse(first.intersection, s))
[set(['a', 'b']), set(['e', 'f'])]

Related

Combinations by list in nested lists in Python

I have a list of the form [['a','b','c','d'], ['a','c','d'], ['b','d','e','f','g','h'], ... ,['c','d','a','b']] and I have to combine the elements of each nested list (separately) in 2-tuples to form a single 2-tuples' list. I have tried to do it with the following code but it only combines the elements of the first list:
def totwotuples(my_list):
for i in range(len(my_list)):
for j in range(len(my_list[i])):
twotuples = itertools.combinations(my_list[i], 2)
return[k for k in twotuples]
How can I iterate over all nested lists? in order to get this expected output (e.g. for first two nested lists): [('a','b'), ('a','c'), ('a','d'), ('b','c'), ('b','d'), ('c','d'), ('a','c'), ('a','d'), ('c','d'), ...]
You can use itertools.chain or itertools.chain.from_iterable to combine the results from sublists.
import itertools
lst = [['a','b','c','d'], ['a','c','d']]
output = itertools.chain.from_iterable(itertools.combinations(sublst, r=2) for sublst in lst)
output = list(output) # convert to a list
print(output) # [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd'), ('a', 'c'), ('a', 'd'), ('c', 'd')]

Remove tuples with same elements in two lists

a=['-a', ('-c', 'd'), ('-d', 'c')]
b=['-b', ('c', '-d'), ('d', '-c')]
Basicly, for each list, if there is some tuple in another list that has the same elements with it, then remove all of those tuples have this elements from both lists.
(I was using sets instead of tuples, but somewhere in my code got an error
says: unhashable type: 'set', so I changed it to tuples...)
res=[]
for i in a:
for j in b:
if type(i) == tuple and type(j) == tuple:
if i[0] in j and i[1] in j:
res.append(i)
res.append(j)
a,b=list(set(a)-set(res)),list(set(b)-set(res))
print(a,b)
This gives a=['a'],b=['-b'], is there better methods (maybe some simple build in function) to do the same thing ?
More examples
>>>a=['-a', ('-c', 'd'), ('-d', 'c'), ('-d', 'c')]
>>>b=['-b', ('c', '-d'), ('d', '-c'), ('-d', 'c')]
>a=['a'],b=['-b']
>>>a=['-a', ('a', 'b'),('-c', 'd'), ('-d', 'c'), ('-d', 'c')]
>>>b=['-b', ('c', '-d'), ('d', '-c'), ('-d', 'c')]
>a=['a',('a', 'b')],b=['-b']
Use frozenset On the sub items and you will be able to use set.difference:
a = ['-a', ('a', 'b'),('-c', 'd'), ('-d', 'c'), ('-d', 'c')]
b = ['-b', ('c', '-d'), ('d', '-c'), ('-d', 'c')]
seta = {frozenset(i) if isinstance(i, tuple) else i for i in a}
setb = {frozenset(i) if isinstance(i, tuple) else i for i in b}
print(seta - setb, setb - seta)
Prints:
{'-a', frozenset({'a', 'b'})} {'-b'}
I only say this because you said you were using sets before but had issues. You can always turn the frozen sets back to tuple.
Please find the following answer. Basically, you just need to find out duplicates first.
a = ['-a', ('-c', 'd'), ('-d', 'c')]
b = ['-b', ('-c', 'd'), ('d', '-c')]
to_remove = set(a).intersection(set(b))
a = [i for i in a if i not in to_remove or type(i) != tuple]
b = [j for j in b if j not in to_remove or type(j) != tuple]
print a, b

Function does not store all the output

I have the following list,
p=[list(['a', 'b', 'c']), list(['d', 'e'])]
I would like to make the subset of each element (of size 2) and list them, this would give the output as follow:
[[('a', 'b'), ('a', 'c'), ('b', 'c')],[('d', 'e')]]
To achieve this I wrote the following function,
def x(m,n):
for i in x:
z=list(itertools.combinations(i, n))
return(z)
yet when I apply ie z(m,2) I only get the last element:
[('d', 'e')]
I wonder what am I doing wrong?
it is because you are setting z each time instead of appending it:
def x(m,n):
z = []
for i in m:
z.append(list(itertools.combinations(i, n)))
return(z)
yileds:
[[('a', 'b'), ('a', 'c'), ('b', 'c')], [('d', 'e')]]

Creating pairs of objects in a list

I have a list of objects:
object_list = ['distance', 'alpha1', 'alpha2', 'gamma']
I want to obtain a new list with a pair combination of those objects, such as:
new_list = [ ['distance', 'alpha1'], ['distance', 'alpha2'], ['distance', 'gamma'],['alpha1', 'alpha2'], [ 'alpha1', 'gamma'] ... ]
Generally I will obtain 24 sublists(cases).
itertools.combinations if order isn't important or itertools.permutations if order matters
itertools.combinations
>>> a = ['a', 'b', 'c']
>>> list(itertools.combinations(a, 2))
('a', 'b'), ('a', 'c'), ('b', 'c')] # Order isn't important
itertools.permutations
>>> a = ['a', 'b', 'c']
>>> list(itertools.permutations(a, 2))
[('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')] #Order matters
Have a look at itertools - itertools.combinations seems to be the thing you are looking for. use like
import itertools
object_list = ['distance', 'alpha1', 'alpha2', 'gamma']
new_list = list(itertools.combinations(object_list, 2))

Python : Splitting multidimensional lists

I have a list in the form of
[(u'a1', u'b1'),
(u'a1', u'b2'),
(u'c1', u'c2')]
I want it two be split into two lists/columns like
list1 list2
[(u'a1', [(u'b1'),
(u'a1', (u'b2'),
(u'c1')] (u'c2')]
Conversion of unicode to string would also help!
Also, in another case, I have list in the form of
[(('a', 'c'), -3), (('a', 'd'), -7), (('c', 'd'), -4)]
I need the input in the form of
('a','a','c')
('c','d','d')
(-3,-7,-4)
Any tips?
You could create two new list using lists comprehension:
x=[(u'a1', u'b1'),
(u'a1', u'b2'),
(u'c1', u'c2')]
list1 = [i[0] for i in x]
list2 = [i[1] for i in x]
The second example:
>>> L = [(('a', 'c'), -3), (('a', 'd'), -7), (('c', 'd'), -4)]
>>> zip(*[(a[0], a[1], b) for a, b in L])
[('a', 'a', 'c'), ('c', 'd', 'd'), (-3, -7, -4)]
It first flattens each item and then transposes the list.

Categories

Resources