在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