【问题标题】:Make dictionary keys to be the same for common values of two different dictionaries使两个不同字典的公共值的字典键相同
【发布时间】:2019-01-30 16:03:24
【问题描述】:

我有两个字典 dic1 和 dic2,它们具有共同的值但不同的键。 例如:

dic1 = {'M_001': 'gly-glu-L', 'M_002': 'Ala-Gln'}
dic2 = {'M_003': 'gly-glu-L', 'M_004': 'Ala-Gln'}

我使用以下代码来检索两者之间的共同值:

match = []
for value1 in dic1.values():
    for value2 in dic2.values():
        if value1 == value2:
            match.append(value1)

接下来,对于两个字典中的每个公共值,我希望拥有相同的键。

第一个宾语:

dic1 = {'M_003': 'gly-glu-L', 'M_004': 'Ala-Gln'}

dic2 = {'M_003': 'gly-glu-L', 'M_004': 'Ala-Gln'}

具有唯一标识符的第二个目标:

dic1 = {'MX_001': 'gly-glu-L', 'MX_002': 'Ala-Gln'}

dic2 = {'MX_001': 'gly-glu-L', 'MX_002': 'Ala-Gln'}

我需要一些有关如何继续的信息,因为我被困在这个阶段。

谢谢!

【问题讨论】:

  • 所以如果值匹配,您希望dic1 具有与dic2 相同的键,这是预期的输出吗?并将dic2 作为我们比较的基准
  • 是的@aws_apprentice 就是这样
  • 另外两个comun`s ;o)
  • 如果有不匹配的值怎么办,保留原始dict中的key?
  • 目标是只更改每个公共值的键。不匹配的值应保留原始键。

标签: python python-3.x


【解决方案1】:
def tmp(d1, d2):
    # create 2 new dicts where the key and values are reversed
    rd1 = dict((v,k) for k,v in d1.items())  
    rd2 = dict((v,k) for k,v in d2.items())
    for v in set(rd1.keys()) & set(rd2.keys()):
        # cycle over the common values
        del d1[rd1[v]] # delete the old_key from the first dict
        d1[rd2[v]] = v # set the value with the same key as the second one

def tmp2(d1, d2):
    # solution for a "multiple key, same value in first dict" situation 
    rd1 = {}
    for k,v in d1.items():
        if v not in rd1: # could use a defaultdict to avoid this
            rd1[v] = []
        rd1[v].append(k)
    rd2 = dict((v,k) for k,v in d2.items())
    for v in set(rd1.keys()) & set(rd2.keys()):
        for k in rd1[v]: # delete all the (old) keys
            del d1[k]
        d1[rd2[v]] = v

from random import randrange
def tmp3(d1, d2):
    rd1 = {}
    for k,v in d1.iteritems():
        if v not in rd1: 
            rd1[v] = []
        rd1[v].append(k)
    rd2 = dict((v,k) for k,v in d2.iteritems())
    for v in set(rd1.keys()) & set(rd2.keys()):
        for k in rd1[v]:
            del d1[k]
        while 1:
            # attention here: if you'd have more than 100 new keys you'll end up with an infinite loop, adjust for your case
            # I've used 100 to maintain the 3 digit format   
            new_key = "MX_%03d" % randrange(100)

            if new_key not in d1: break
        d1[new_key] = v

def tmp4(d1, d2):
    # solution for your final form of the second objective
    # please stop changing the question :D
    rd1 = {}
    for k,v in d1.iteritems():
        if v not in rd1: 
            rd1[v] = []
        rd1[v].append(k)
    rd2 = {}
    for k,v in d2.iteritems():
        if v not in rd2: 
            rd2[v] = []
        rd2[v].append(k)
    for i, v in enumerate(set(rd1.keys()) & set(rd2.keys())):
        for k in rd1[v]:
            del d1[k]
        for k in rd2[v]:
            del d2[k]
        new_key = "MX_%03d" % i # nothimg more random than counter, see: https://xkcd.com/221/
        d1[new_key] = v
        d2[new_key] = v


dic1 = {'M_001': 'gly-glu-L', 'M_002': 'Ala-Gln'}
dic2 = {'M_003': 'gly-glu-L', 'M_004': 'Ala-Gln'}
if __name__ == '__main__':
    print dic1
    print dic2
    tmp(dic1,dic2)
    print
    print dic1
    print dic2

给予

{'M_001': 'gly-glu-L', 'M_002': 'Ala-Gln'}
{'M_004': 'Ala-Gln', 'M_003': 'gly-glu-L'}

{'M_004': 'Ala-Gln', 'M_003': 'gly-glu-L'}
{'M_004': 'Ala-Gln', 'M_003': 'gly-glu-L'}

如果您有多个具有相同值的键需要不同的方法,则可能会出现问题。

【讨论】:

  • 感谢您的快速回答:对于这种情况,没有多个具有相同值的键,所以这应该可以正常工作!
  • 打败我。反向查找字典,在值上设置交集,O(n)。 OP 有 O(n^2)。我会担心碰撞,但你提到了。
  • 它需要为第一个字典的每个值保留一个键列表,但是如果在第二个字典中有多个具有相同值的键......那么“乐趣”就开始了:D
  • 现在想象我想为每个公共值创建新的唯一键,而不是使用第二个字典键作为基础。例如,像 'MX_***' * 这样的新键是随机数我该怎么做?
  • tmp3 给你随机密钥,你欠我一杯啤酒,它应该是一个 RTFM 答案:)。
【解决方案2】:

如果您不想创建额外的倒排副本,您可以制作单独的列表和字典来执行以下任务:

def comun(dict1, dict2):
        # get common information
        emptyDict = {}
        removeList = []
        for d1key, d1val in dict1.items():
            for d2key, d2val in dict2.items():
                if (d1val == d2val):
                    removeList.append(d1key)
                    emptyDict[d2key] = d2val
                    break

        # remove repeated elements
        for item in removeList:
            del dict1[item]

        # add common elements
        dict1.update(emptyDict)

dict1 = {'M_001': 'gly-glu-L', 'M_002': 'Ala-Gln'}
dict2 = {'M_003': 'gly-glu-L', 'M_004': 'Ala-Gln'}
if __name__ == '__main__':
    print(dict1)
    print(dict2)
    comun(dict1,dict2)
    print(dict1)
    print(dict2)

【讨论】:

  • 超大字典的特殊情况是循环遍历两者?没有:)
  • 显然,它在速度方面很糟糕。但可以节省内存(我猜)
猜你喜欢
  • 2016-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多