In python, I have a dictionary like this...
pleio = {'firstLine': {'enf1': ['54', 'set'],
'enf2': ['48', 'free'],
'enf3': ['34', 'set'],
'enf4': ['12', 'free']}
'secondLine':{'enf5': ['56','bgb']
'enf6': ['67','kiol']
'enf7': ['11','dewd']
'enf8': ['464','cona']}}
I would like to make paired combinations with no repetition of the elements in the inner dictionary, to end up with a result like this...
{'enf3': ['34', 'set'], 'enf2': ['48', 'free']}
{'enf3': ['34', 'set'], 'enf1': ['54', 'set']}
{'enf3': ['34', 'set'], 'enf4': ['12', 'free']}
{'enf2': ['48', 'free'], 'enf1': ['54', 'set']}
{'enf2': ['48', 'free'], 'enf4': ['12', 'free']}
{'enf1': ['54', 'set'], 'enf4': ['12', 'free']}
I built a function which lets me do it...
import itertools
def pairwise():
'''
'''
leti=[]
for snp, enfs in pleio.items():
for x in itertools.combinations(enfs, 2 ):
leti.append(x)
pleopairs=[]
for i in leti:
pipi={}
for c in i:
pipi[c]= enfs[c]
pleopairs.append(pipi)
..but i was wondering if there's a more efficient way, like another specific function from itertools, or any other source. By the way, I found a function called "pairwise" in the itertools documentation. But I don't know how to adapt it, if would be possible in my case, or improve my attempt. Any help?
Your combinations
approach was correct, you just need to turn the results of each combination into a dict again:
import itertools
def pairwise(input):
for values in input.itervalues():
for pair in itertools.combinations(values.iteritems(), 2):
yield dict(pair)
This version is a generator, yielding pairs efficiently, nothing is held in memory any longer than absolutely necessary. If you need a list, just call list()
on the generator:
list(pairwise(pleio))
Output:
>>> from pprint import pprint
>>> pprint(list(pairwise(pleio)))
[{'enf2': ['48', 'free'], 'enf3': ['34', 'set']},
{'enf1': ['54', 'set'], 'enf3': ['34', 'set']},
{'enf3': ['34', 'set'], 'enf4': ['12', 'free']},
{'enf1': ['54', 'set'], 'enf2': ['48', 'free']},
{'enf2': ['48', 'free'], 'enf4': ['12', 'free']},
{'enf1': ['54', 'set'], 'enf4': ['12', 'free']}]
You can even combine the whole thing into a one-liner generator:
from itertools import combinations
for paired in (dict(p) for v in pleio.itervalues() for p in combinations(v.iteritems(), 2)):
print paired
Which outputs:
>>> for paired in (dict(p) for v in pleio.itervalues() for p in combinations(v.iteritems(), 2)):
... print paired
...
{'enf3': ['34', 'set'], 'enf2': ['48', 'free']}
{'enf3': ['34', 'set'], 'enf1': ['54', 'set']}
{'enf3': ['34', 'set'], 'enf4': ['12', 'free']}
{'enf2': ['48', 'free'], 'enf1': ['54', 'set']}
{'enf2': ['48', 'free'], 'enf4': ['12', 'free']}
{'enf1': ['54', 'set'], 'enf4': ['12', 'free']}
If you are on Python 3, replace .itervalues()
and .iteritems()
by .values()
and .items()
respectively.
If you want all pair combinations, you could probably use the following which is shorter, but I would not say this is more efficient.
[dict([(x,vx),(y,vy)]) for (x,vx) in pleio['firstLine'].iteritems()
for (y,vy) in pleio['firstLine'].iteritems()
if x < y]
Output
[{'enf3': ['34', 'set'], 'enf4': ['12', 'free']},
{'enf2': ['48', 'free'], 'enf3': ['34', 'set']},
{'enf2': ['48', 'free'], 'enf4': ['12', 'free']},
{'enf1': ['54', 'set'], 'enf3': ['34', 'set']},
{'enf1': ['54', 'set'], 'enf2': ['48', 'free']},
{'enf1': ['54', 'set'], 'enf4': ['12', 'free']}]