如何根据值更新字典键?

问题描述

我有两个字典,它们的值相似,但是键不同。我想用第一个字典db的键值更新第二个字典user

在不使逻辑过于复杂的情况下实现该目标的最佳方法是什么?

例如,我有以下词典:

user = {'school': ['books','pencils','sheets','notebooks']}
db = {'education': ['books','notebooks'],'actors': ['student','teacher','principal']}

user['school']db['education']具有相同的列表值。我只想用db中的键值更新user中的键值。我认为实现的方式如下:

def get_key(my_dict,val):
    for key,value in my_dict.items():
        if val == value: 
            return key 
    return None

res = {}
for key,value in db.items():
    if value in user.values():
        key_user = get_key(user,value)
        if key_user:            
            res.update({key_user: value})
    else:
        res.update({key: value})

print(res)

我正在Python 3.6.6中实现此功能,因此据我了解,字典条目的顺序得以保留。

所需的输出如下:

{'school': ['books','principal']}

解决方法

正如您所说的,顺序很重要,我认为最简单的方法是重新创建字典,但是对于较大的数据集来说效率不高。

我们可以迭代db来重新创建它,我们唯一需要看的就是使用user还是db中的密钥。如果密钥存在于user_values内,那么我们可以获取它的索引并使用该索引从user_keys获取密钥,否则我们使用key

user = {'school': ['books','pencils','sheets','notebooks']}
db = {'education': ['books','notebooks'],'actors': ['student','teacher','principal']}

user_keys = tuple(user.keys())
user_values = tuple(user.values())

new_db = {user_keys[user_values.index(value)] if value in user_values else key: value for key,value in db.items()}

>>> {'school': ['books','principal']}
,

我喜欢Serial Lazeranswer,它的用法相反,但是其余的有些笨拙,恕我直言。我会改做一个普通的for循环:

x = {'a': [1,2,3]}  # "user"
y = {'b': [1,3],'c': [4,5,6]}  # "db"

rev = {tuple(v): k for k,v in x.items()}
result = {}
for k,v in y.items():
    try:
        k = rev[tuple(v)]
    except KeyError:
        pass
    result[k] = v

print(result)  # -> {'a': [1,6]}

或者,如果可以将所有dict反转,将其值转换为元组然后再返回,则可以使用ChainMap

from collections import ChainMap

c = ChainMap(*[{tuple(v): k for k,v in d.items()} for d in (x,y)])
result = {v: list(k) for k,v in c.items()}

或者只是一个简单的字典:

x_rev,y_rev = [{tuple(v): k for k,y)]
y_rev.update(x_rev)
result = {v: list(k) for k,v in y_rev.items()}
,

如果为user字典创建反向循环字典,则可能会更有效率。

逻辑减少到仅两行代码:

reverse_user = {tuple(user[key]):key for key in user}

new_db_dict = {reverse_user[tuple(db[db_key])]:db[db_key] for db_key in db if tuple(db[db_key]) in reverse_user}

new_db_dict_excl = {key:db[key] for key in db if tuple(db[key]) not in reverse_user}

new_db_dict.update(new_db_dict_excl)
,

当我们意识到可以用db更新整个user时,我们可以简化它。我们需要确定的是在更新之前要删除哪些键,同时还要注意在迭代时不要修改db

user = {'school': ['books','principal']}

for user_value in user.values():
    for del_key in [db_key for db_key,db_value in db.items() if user_value == db_value]:
        del db[del_key]

db.update(user)

>>> {'actors': ['student','principal'],'school': ['books','notebooks']}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...