Combinations by list in nested lists in Python - 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')]

Related

Convert list of tuples such that [(a,b,c)] converts to [(a,b),(a,c)]

Thoughts on how I would do this? I want the first value in the tuple to pair with each successive value. This way each resulting tuple would be a pair starting with the first value.
I need to do this: [(a,b,c)] --> [(a,b),(a,c)]
You can try this.
(t,)=[('a','b','c')]
[(t[0],i) for i in t[1:]]
# [('a', 'b'), ('a', 'c')]
Using itertools.product
it=iter(('a','b','c'))
list(itertools.product(next(it),it))
# [('a', 'b'), ('a', 'c')]
Using itertools.repeat
it=iter(('a','b','c'))
list(zip(itertools.repeat(next(it)),it))
# [('a', 'b'), ('a', 'c')]
a = [('a','b','c')]
a = a[0]
a = [tuple([a[0], a[index]]) for index in range(1, len(a))]
Try this !
A solution that uses itertools's combinations module.
from itertools import combinations
arr = (['a','b','c'])
for i in list(combinations(arr, 2)):
if(i[0]==arr[0]):
print(i ,end = " ")
This would give a solution ('a', 'b') ('a', 'c')
You can just append pairs of tuples to a list:
original = [(1,2,3)]
def makePairs(lis):
ret = []
for t in lis:
ret.append((t[0],t[1]))
ret.append((t[0],t[2]))
return ret
print(makePairs(original))
Output:
[(1, 2), (1, 3)]
If your tuples are arbitrary length you can write a simple generator:
def make_pairs(iterable):
iterator = iter(iterable)
first = next(iterator)
for item in iterator:
yield first, item
example result:
my_tuple = ('a', 'b', 'c', 'd')
list(make_pairs(my_tuple))
Out[170]: [('a', 'b'), ('a', 'c'), ('a', 'd')]
This is a memory-efficient solution.

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

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.

Removing duplicates from tuples within a list

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

Categories

Resources