在python中修改嵌套字典中的键和值
我正在使用一个嵌套字典,并试图找出如何有效地修改某些嵌套和非嵌套键/值。简言之,我正努力做到以下几点:在python中修改嵌套字典中的键和值,python,dictionary,nested,Python,Dictionary,Nested,我正在使用一个嵌套字典,并试图找出如何有效地修改某些嵌套和非嵌套键/值。简言之,我正努力做到以下几点: 获取嵌套值并使用非嵌套键进行切换 重命名嵌套键 下面是我正在使用的词典的一个基本示例: pet_dictionary = {'Buford':{'color':'white', 'weight': 95, 'age':'3', 'breed':'bulldog'}, 'Henley':{'color':'blue',
pet_dictionary = {'Buford':{'color':'white', 'weight': 95, 'age':'3',
'breed':'bulldog'},
'Henley':{'color':'blue', 'weight': 70, 'age':'2',
'breed':'bulldog'},
'Emi':{'color':'lilac', 'weight': 65, 'age':'1',
'breed':'bulldog'},
}
我想获取非嵌套键,即每只狗的名称(即Buford、Henley、Emi),将其与年龄的嵌套值(即3、2、1)进行切换,然后将嵌套键名称从“年龄”更改为“名称”。因此输出应如下所示:
pet_dictionary = {'3':{'color':'white', 'weight': 95, 'name':'Buford',
'breed':'bulldog'},
'2':{'color':'blue', 'weight': 70, 'name':'Henley',
'breed':'bulldog'},
'1':{'color':'lilac', 'weight': 65, 'name':'Emi',
'breed':'bulldog'},
}
我知道如何一个接一个地手动操作,但我不确定以更优雅/最佳的方式进行所有这些更改的最佳方法是什么。这可能会有所帮助
pet_dictionary = {'Buford':{'color':'white', 'weight': 95, 'age':'3',
'breed':'bulldog'},
'Henley':{'color':'blue', 'weight': 70, 'age':'2',
'breed':'bulldog'},
'Emi':{'color':'lilac', 'weight': 65, 'age':'1',
'breed':'bulldog'},
}
d = {}
for k,v in pet_dictionary.items():
d[v['age']] = pet_dictionary[k]
d[v['age']].update({"name": k})
del d[v['age']]['age']
print d
输出:
{'1': {'color': 'lilac', 'breed': 'bulldog', 'name': 'Emi', 'weight': 65}, '3': {'color': 'white', 'breed': 'bulldog', 'name': 'Buford', 'weight': 95}, '2': {'color': 'blue', 'breed': 'bulldog', 'name': 'Henley', 'weight': 70}}
如果可以更改以前的词典,则可以执行以下操作:
def flip(k, v):
v.update(name=k)
return v.pop('age'), v
通过一些理解,您可以进行如下转换: 代码: 测试代码: 结果:
在迭代字典时,您可以通过三个步骤干净地构建一个新字典:
# Preserves original dict
d = {}
for k, v in pet_dictionary.items():
key = v["age"] # 1. grab the new key
d[key] = {"name": k} # 2. add new "name" item
d[key].update({k_:v_ for k_, v_ in v.items() if k_!="age"}) # 3. update the new dict
d
在这种情况下,蟒蛇们开始崭露头角
p = {'Buford':{'color':'white', 'weight': 95, 'age':'3',
'breed':'bulldog'},
'Henley':{'color':'blue', 'weight': 70, 'age':'2',
'breed':'bulldog'},
'Emi':{'color':'lilac', 'weight': 65, 'age':'1',
'breed':'bulldog'},
}
new_dictionary = {p[i]['age']:{'color':p[i]['color'],'weight':p[i]['weight'],
'name':i,'breed':p[i]['breed']} for i in p}
输出:
{'3': {'color': 'white', 'weight': 95, 'name': 'Buford', 'breed': 'bulldog'},
'2': {'color': 'blue', 'weight': 70, 'name': 'Henley', 'breed': 'bulldog'},
'1': {'color': 'lilac', 'weight': 65, 'name': 'Emi', 'breed': 'bulldog'}}
有,
Python 3.8的更新:
只有在可以接受对原始dict进行修改的情况下(感谢@pylang注意到这一点),使用字典才有简洁的语法:
new = {nested.pop('age'): {**nested, 'name': name} for name, nested in pet_dictionary.items()}
这是一个两行:
##add new value, which was formerly the key
{k: v.update({'name':k}) for k,v in pet_dictionary.items()}
##reset keys to value of 'age'
new_pet = {v.get('age'): v for k,v in pet_dictionary.items()}
在几行中执行此操作,不需要任何额外的LIB,但对原始词典进行变异:
pet_dictionary = {
nested.pop('age'): nested.update({'name': name}) or nested
for name, nested in pet_dictionary.items()
}
import copy
new_pet_dict = {
nested.pop('age'): nested.update({'name': name}) or nested
for name, nested in copy.deepcopy(pet_dictionary).items()
}
并具有额外的导入功能,但不发生变异pet\u字典:
pet_dictionary = {
nested.pop('age'): nested.update({'name': name}) or nested
for name, nested in pet_dictionary.items()
}
import copy
new_pet_dict = {
nested.pop('age'): nested.update({'name': name}) or nested
for name, nested in copy.deepcopy(pet_dictionary).items()
}
…保留原始的pet\u字典
不变
信息
最初,我发布了不同的答案,其中键入使用.pop
方法创建的新dict,以及使用{**nested,'name':name}
创建的嵌套dict,但它不起作用。这将是一个更干净的解决方案,但另一方面,解释器从右到左读取代码,然后。。。显然,使用这种方法是行不通的
那么这是怎么回事?它看起来有点棘手,尤其是线条:
nested.update({'name': name}) or nested
但让我们仔细看看。我们需要使用name
键更新嵌套,但它不返回任何值,并对对象进行变异。所以这个或
的左边部分总是无
,我们希望在我们的dict理解中有dict
对象。下面是Python中的短路求值
,如果第一个操作数是falsy,它总是返回第二个操作数
无变异示例使用
deepcopy
并变异临时副本,而不是原始词典 我想你可以用d[v[“age”]]
来缩短d[pet_dictionary[k]['age']]]
,这就是方法。干得好。唯一的问题是如果可以接受的话,对原始的dict进行变异。一种非破坏性的方法可能是使用另一种理解方法new={nested['age']:{**{k:v代表k,v在nested if k!=“age”}代表name,嵌套在pet_dictionary.items()中
好吧,我有时更喜欢像你这样的解决方案,显式循环更清晰。是的,只有在以前的dict不再使用的情况下,它才是可以接受的。如果可以,我将使用for循环的初始解决方案,因为嵌套理解的可读性要低得多。请注意,从概念上讲,你不能更改字典中的键:如果你是要修改原始版本,必须删除旧的键值关联并添加一个新的键值关联(具有相同的值)。您提到了迭代器。您特别指的是什么?Python字典是可编辑的,这意味着您可以使用{i for i in dict}语法与我上面所做的一样!正确。您使用的是字典理解,它是可编辑的,而不是。这些很容易混淆。这里有一个快速测试:迭代器必须与iter()
和next()
一起使用。如果您尝试next(新字典)
你会看到TypeError:“dict”对象不是迭代器。所以你必须编辑第一行。否则,做得很好。第一:变异v
对你的第一理解没有好处,这会无缘无故地创建带有None
值的dict。第二:age
仍然是你的新宠物的关键ict(您可以使用pop
而不是get
来修复它)。
pet_dictionary = {
nested.pop('age'): nested.update({'name': name}) or nested
for name, nested in pet_dictionary.items()
}
import copy
new_pet_dict = {
nested.pop('age'): nested.update({'name': name}) or nested
for name, nested in copy.deepcopy(pet_dictionary).items()
}
nested.update({'name': name}) or nested