Python 字典中元素的成对组合,不重复

Python 字典中元素的成对组合,不重复,python,combinatorics,itertools,Python,Combinatorics,Itertools,在python中,我有一个这样的字典 pleio = {'firstLine': {'enf1': ['54', 'set'], 'enf2': ['48', 'free'], 'enf3': ['34', 'set'], 'enf4': ['12', 'free']} 'secondLine':{'enf5': ['56','bgb']

在python中,我有一个这样的字典

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']}}
我想在内部字典中进行成对组合,不重复元素,最终得到这样的结果

{'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']}
我建立了一个函数,让我做它

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)

…但我想知道是否有更有效的方法,比如来自itertools的另一个特定函数,或任何其他来源。顺便说一下,我在文档中找到了一个名为“pairwise”的函数。但我不知道如何适应它,如果在我的情况下可能的话,或者改进我的尝试。有什么帮助吗?

如果您想要所有的线对组合,您可能可以使用以下较短的线对组合,但我不会说这更有效

[dict([(x,vx),(y,vy)]) for (x,vx) in pleio['firstLine'].iteritems()
                       for (y,vy) in pleio['firstLine'].iteritems()
                       if x < y]

如果您想要所有的线对组合,您可能会使用以下较短的线对组合,但我不会说这更有效

[dict([(x,vx),(y,vy)]) for (x,vx) in pleio['firstLine'].iteritems()
                       for (y,vy) in pleio['firstLine'].iteritems()
                       if x < y]

您的
组合方法是正确的,您只需将每个组合的结果再次转换为dict:

import itertools

def pairwise(input):
    for values in input.itervalues():
        for pair in itertools.combinations(values.iteritems(), 2):
            yield dict(pair)
这个版本是一个生成器,可以高效地生成对,内存中没有比绝对需要的时间更长的东西。如果需要列表,只需在生成器上调用
list()

list(pairwise(pleio))
from itertools import combinations

for paired in (dict(p) for v in pleio.itervalues() for p in combinations(v.iteritems(), 2)):
    print paired
输出:

>>> 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']}]
您甚至可以将整个过程组合成一个线性生成器:

list(pairwise(pleio))
from itertools import combinations

for paired in (dict(p) for v in pleio.itervalues() for p in combinations(v.iteritems(), 2)):
    print paired
哪些产出:

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

如果您使用的是Python 3,请将
.itervalues()
.iteritems()
分别替换为
.values()
.items()

您的
组合方法是正确的,您只需将每个组合的结果再次转换为dict:

import itertools

def pairwise(input):
    for values in input.itervalues():
        for pair in itertools.combinations(values.iteritems(), 2):
            yield dict(pair)
这个版本是一个生成器,可以高效地生成对,内存中没有比绝对需要的时间更长的东西。如果需要列表,只需在生成器上调用
list()

list(pairwise(pleio))
from itertools import combinations

for paired in (dict(p) for v in pleio.itervalues() for p in combinations(v.iteritems(), 2)):
    print paired
输出:

>>> 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']}]
您甚至可以将整个过程组合成一个线性生成器:

list(pairwise(pleio))
from itertools import combinations

for paired in (dict(p) for v in pleio.itervalues() for p in combinations(v.iteritems(), 2)):
    print paired
哪些产出:

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

如果您使用的是Python 3,请将
.itervalues()
.iteritems()
分别替换为
.values()
.items()

enfs
将是
pleio
处理的最后一个值。这几乎肯定不是你想要使用的。不清楚您在函数的后半部分想做什么。pleio是否有多个键?是的,pleio有几百个键。。。为了简单起见,我只写了一篇。在函数的第二部分中,我只是迭代字典,收集元组对中每个元素的值,构建两个元素的字典,并将它们附加到一个列表中。然后您将得到错误的结果,这一步骤不是必需的。但实际上它是有效的。。。为什么不正确?
enfs
将是
pleio
处理的最后一个值。这几乎肯定不是你想要使用的。不清楚您在函数的后半部分想做什么。pleio是否有多个键?是的,pleio有几百个键。。。为了简单起见,我只写了一篇。在函数的第二部分中,我只是迭代字典,收集元组对中每个元素的值,构建两个元素的字典,并将它们附加到一个列表中。然后您将得到错误的结果,这一步骤不是必需的。但实际上它是有效的。。。为什么不正确?我尝试使用长度大于1的词典,并意识到我的错误。。。我正在纠正它的路上,但这个解决方案绝对令人惊讶。无论如何,我想知道为什么itertools没有一个简单的成对生成器来实现这一点。再次感谢@这是一个简单的成对生成器。您只需将输出返回到所需的格式(您输入的是键值元组,而不是字典,因此输出的是元组,而不是字典)。是的,我的意思是像这样的“一个简单的生成器”。@peixe:我们所做的就是将特定的嵌套输入格式转换为所需的输出格式。库根据您想要的规则为您生成配对:不重复的组合。如果不变得过于具体而无法普遍使用,该库将无能为力。我尝试使用长度大于1的词典,并意识到我的错误。。。我正在纠正它的路上,但这个解决方案绝对令人惊讶。无论如何,我想知道为什么itertools没有一个简单的成对生成器来实现这一点。再次感谢@这是一个简单的成对生成器。您只需将输出返回到所需的格式(您输入的是键值元组,而不是字典,因此输出的是元组,而不是字典)。是的,我的意思是像这样的“一个简单的生成器”。@peixe:我们所做的就是将特定的嵌套输入格式转换为所需的输出格式。库根据您想要的规则为您生成配对:不重复的组合。如果不变得过于具体而无法普遍使用,那么这个库就没有什么可以做的了。