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

invert key and value in dictionary in python3 (the value not unique)

我知道如何在值唯一时简单地反转字典中的键和值。 但是当值不唯一时如何反转。 根据要求,如果这个值出现不止一次,我需要用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()))

我的错误输出是[(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()

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

d = {1,{'a','c'},2,{'b','c'}}

而是字典

d = {1:{'a','c'}, 2:{'b','c'}}

请仔细检查这里:-)。

无论如何,我会这样做:

import collections

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

如果 dict 子类 defaultdict 可以,则 return 可以简化为 return result -- 这是唯一必要的如果规范对此非常严格,则将其变成 dict

我想下一步可​​能是 "oops, imports are not allowed" 禁止 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

添加:显然最新版本是至关重要的(当然 OP "forgot" 首先添加 "no imports" 约束——为什么他们继续 doing 这对我来说?!他们会花费 anything 来揭示 all 从一开始就在他们的问题中的约束吗?!?!? !!) 但需要进行调整——需要将单例集转换为其唯一元素的非集(一个可怕的、可怕的、不好的规范,使得生成的字典几乎无法使用,并且让我强烈希望有一个对那些似乎相信制定令人作呕的糟糕规格可以改善他们的教学的无礼小人说几句尖锐的话,但是,那是另一种咆哮。

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

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}

没什么难的:只是 "unwinding" 单身人士用 pop 设置了他们的一项。 (接下来 - 另一个 愚蠢的任意约束的迟来启示,例如 "no if/else expressions"?!-)

添加(保留上面的错误代码):需要在return语句中使用result而不是d清楚!即最后一行必须是

    return {k: result[k] if len(result[k])>1 else result[k].pop() for k in result}