【问题标题】:Pair combinations of elements in dictionary without repetition字典中元素的配对组合不重复
【发布时间】:2012-11-26 10:12:05
【问题描述】:

在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 或任何其他来源的另一个特定功能。顺便说一句,我在itertools 文档中找到了一个名为“pairwise”的函数。但我不知道如何适应它,如果可能的话,或者改进我的尝试。有什么帮助吗?

【问题讨论】:

  • enfs 将是来自pleio 处理的最后一个值。它几乎肯定不是您想要使用的。目前尚不清楚您在函数的后半部分想要做什么。
  • pleio 有多个密钥吗?
  • 是的,pleio 有几百个键……为了简单起见,我只写了一个。在函数的第二部分,我只是迭代字典,收集元组对中每个元素的值并构建两个元素的字典,并将它们附加到列表中。
  • 那你会得到不正确的结果,这个步骤是没有必要的。
  • 但它确实有效...为什么不正确?

标签: python combinatorics itertools


【解决方案1】:

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

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

您甚至可以将整个东西组合成一个单行生成器:

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()

【讨论】:

  • 我尝试使用长度 > 1 的字典并意识到我的错误......我正在纠正它的路上,但这个解决方案绝对令人惊叹。无论如何,我想知道为什么 itertools 没有一个简单的成对生成器。再次感谢!
  • @peixe:这是一个简单的成对生成器。您只需要将输出转换回您想要的格式(您输入的是键值元组,而不是字典,因此输出是元组,而不是字典)。
  • 是的,我的意思是像这样的“简单的生成器”。
  • @peixe:我们所做的就是采用您特定的嵌套输入格式并将其调整为所需的输出格式。该库根据您想要的规则为您生成对:没有重复的组合。如果不变得过于具体而无法普遍使用,图书馆就没有什么可以做的了。
【解决方案2】:

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

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

输出

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-02
    • 2020-05-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多