在python3中反转字典中的键和值(值不唯一)

viv*_*ian 3 python dictionary duplicates key-value python-3.x

我知道当值是唯一的时,如何简单地在字典中反转键和值.但是当值不唯一时如何反转.根据要求,如果值出现不止一次,我需要使用set来将它们组合在一起.


防爆.输入d = {'a':1, 'b':2,'c':1,'d':2}输出d = {1,{'a','c'},2,{'b','c'}}


我在下面编写了相当愚蠢的代码,但因为我只创建了一个集合,因此所有显示多次的值都在该集合中.

def change(d):

    inverted_l = list(map(lambda t:(t[1],t[0]), d.items()))
    store_key = [] #for store the key to check if value appear more than one
    new_d = {}
    x = set()
    for i in range(len(inverted_l)):
        store_key.append(inverted_l[i][0])
    for i in range(len(store_key)):
        if store_key.count(store_key[i])> 1:
            x.add(inverted_l[i][1]) #I think the problem is I need create set
                                    #each time, but I don't know how to do that
            new_d[store_key[i]] = x
        else:
            new_d[store_key[i]] = inverted_l[i][1]
    return new_d

print(sorted(change({'a':1, 'b':2, 'c':1,'d':2}).items()))
Run Code Online (Sandbox Code Playgroud)

我错了输出[(1, {'c', 'd', 'b', 'a'}), (2, {'c', 'd', 'b', 'a'})]但是我需要[(1, {'a', 'c'}), (2, {'b', 'd'})]

补充:我尝试你的代码,但是当我测试时发生错误print(sorted(invert_dict({'a':1, 'b':2, 'c':1}).items())) 我希望我的结果是[(1, {'a', 'c'}), (2, 'b')] 我是python的新手,谢谢你的帮助和时间!

def invert_dict(d):
    result = {}
    for k in d:
        if d[k] not in result:
            result[d[k]] = set()
        result[d[k]].add(k)
    return {k: d[k] if len(d[k])>1 else d[k].pop() for k in d}



 Traceback (most recent call last):
  File "U:\test.py", line 9, in <module>
    print(sorted(invert_dict({'a':1, 'b':2, 'c':1}).items()))
  File "U:\test.py", line 7, in invert_dict
    return {k: d[k] if len(d[k])>1 else d[k].pop() for k in d}
  File "U:\test.py", line 7, in <dictcomp>
    return {k: d[k] if len(d[k])>1 else d[k].pop() for k in d}
TypeError: object of type 'int' has no len()
Run Code Online (Sandbox Code Playgroud)

Ale*_*lli 5

我很确定你的意思是所需的输出不是设定的

d = {1,{'a','c'},2,{'b','c'}}
Run Code Online (Sandbox Code Playgroud)

而是字典

d = {1:{'a','c'}, 2:{'b','c'}}
Run Code Online (Sandbox Code Playgroud)

只需仔细检查一下:-).

无论如何,我会这样做:

import collections

def invert_dict(d):
    result = collections.defaultdict(set)
    for k in d:
        result[d[k]].add(k)
    return dict(result)
Run Code Online (Sandbox Code Playgroud)

return可以简化为return result,如果dict 子类 defaultdict是确定-它只是需要把它变成一个dict,如果规范是关于十分严谨.

我想下一步可​​能是"哎呀,不允许进口"禁止collections.defaultdict,所以我期待 - 在这种情况下,改为(例如)

def invert_dict(d):
    result = {}
    for k in d:
        if d[k] not in result:
            result[d[k]] = set()
        result[d[k]].add(k)
    return result
Run Code Online (Sandbox Code Playgroud)

补充:显然最新版本是至关重要的(OP当然"忘记"首先添加"无导入"约束 - 为什么他们继续对我这样做?!它会花费他们任何东西来揭示所有的限制从他们的Qs开始前面?!?!?!!)但是需要进行调整 - 单例集需要变成他们唯一元素的非集合(一个可怕的,可怕的,不好的规范,使得结果字典几乎无法使用,并且让我强烈希望对那些似乎相信制作令人作呕的糟糕规格改善他们的教学的没有好词的人有一些尖锐的话语,但是,那是另一种咆哮).

无论如何,最好是添加一个后处理步骤:

def invert_dict(d):
    result = {}
    for k in d:
        if d[k] not in result:
            result[d[k]] = set()
        result[d[k]].add(k)
    return {k: d[k] if len(d[k])>1 else d[k].pop() for k in d}
Run Code Online (Sandbox Code Playgroud)

没什么难的:只需"解开"单件套装就可以了pop.(接下来是什么 - 另一个愚蠢的任意约束的迟来的启示,例如"no if/else表达式"?! - )

新增(上面留下的缺陷代码):需要使用resultdreturn声明中清楚!即最后一行必须是

    return {k: result[k] if len(result[k])>1 else result[k].pop() for k in result}
Run Code Online (Sandbox Code Playgroud)