更新嵌套字典中的键,但在键字符串中有一些例外

时间:2016-12-14 22:36:52

标签: python list dictionary

所以我有一个类似这样的学生名单:

students = [ {'name': 'Jack' , 'status' : 'Average' , 'subjects' : { 'subject1' : 'English' , 'subject2' : 'Math' } , 'height' : '20cm' },
{'name': 'Tom' , 'status' : 'Good' , 'subjects' : { 'subject1' : 'English' , 'subject2' : 'Science' } , 'height' : '30cm' }
 ]

所以上面的列表大小为2.假设尺寸相当大,可以说是50或60或更多。

我想要返回列表 students_output&对于每个学生,我想要返回一个字典,其中包含每个学生的以下值,这些值是从上面的列表中提取的,但稍微修改了一些键'。最终输出应该是这样的:

students_output = [ {'student_name': 'Jack' , 'student_status' : 'Average' , 'student_subjects' : { 'student_subject1' : 'English' , 'student_subject2' : 'Math' } , 'child_height' : '20cm' },
{'student_name': 'Tom' , 'student_status' : 'Good' , 'student_subjects' : { 'student_subject1' : 'English' , 'student_subject2' : 'Science' } , 'child_height' : '30cm' }
 ]

我无法理解如何创建一个有效的循环,以便我的结果数据结构中的密钥按照输出中的提供进行维护,我可以从第一个列表中获取数据。

例如,在students_output中,我知道

students_output[0]['student_name']=students[0]['name']

但是,任何人都可以帮助我反复进行吗?

3 个答案:

答案 0 :(得分:1)

为了实现这一点,您必须在每个键的开头连接"student_",并将"height"键作为一个例外。您可以通过列表理解 dict理解表达式的组合来实现:

students = [ 
    {'name': 'Jack' , 'status' : 'Average' , 'subjects' : { 'subject1' : 'English' , 'subject2' : 'Math' } , 'height' : '20cm' },
    {'name': 'Tom' , 'status' : 'Good' , 'subjects' : { 'subject1' : 'English' , 'subject2' : 'Science' } , 'height' : '30cm' }
]

def get_key(key):
    return {
       'height': 'child_height',  # All exception you need in `key`
                                  # apart from concatenating `"student_"`
       }.get(key, 'student_' + key)

new_list = [{
    get_key(k): ({
         get_key(kk):v  for kk, vv in v.items()} if isinstance(v, dict) else v) \
             for k, v in s.items()
    } for s in students]

new_list保留的值为:

[{'student_name': 'Jack', 'child_height': '20cm', 'student_status': 'Average', 'student_subjects': {'student_subject1': {'subject1': 'English', 'subject2': 'Math'}, 'student_subject2': {'subject1': 'English', 'subject2': 'Math'}}}, 
 {'student_name': 'Tom', 'child_height': '30cm', 'student_status': 'Good', 'student_subjects': {'student_subject1': {'subject1': 'English', 'subject2': 'Science'}, 'student_subject2': {'subject1': 'English', 'subject2': 'Science'}}}]

答案 1 :(得分:0)

这是一个快速而肮脏的功能,可以满足您的需求:

In [10]: def rename_keys(students):
    ...:     d = {}
    ...:     for k,v in students.items():
    ...:         if isinstance(v,dict):
    ...:             k = "student_" + k
    ...:             v = rename_keys(v)
    ...:             d[k] = v
    ...:         elif k == 'height':
    ...:             k = "child_height"
    ...:             d[k] = v
    ...:         else:
    ...:             k = "student_" + k
    ...:             d[k] = v
    ...:     return d
    ...:
    ...:

In [11]: [rename_keys(d) for d in students]
Out[11]:
[{'child_height': '20cm',
  'student_name': 'Jack',
  'student_status': 'Average',
  'student_subjects': {'student_subject1': 'English',
   'student_subject2': 'Math'}},
 {'child_height': '30cm',
  'student_name': 'Tom',
  'student_status': 'Good',
  'student_subjects': {'student_subject1': 'English',
   'student_subject2': 'Science'}}]

实际上,这不一定是递归的,你可以用字典理解来代替递归调用:

v = {'student_'+key:value for key,value in v.items()}

答案 2 :(得分:-1)

您可以在列表推导中使用以下函数,如下所示:

def new_dict(d):
    res = {}
    for key, value in d.iteritems():
        student_or_child = 'student' if key != 'height' else 'child'
        if type(value) == dict:
            res['{}_{}'.format(student_or_child, key)] = new_dict(value)
        else:
            res['{}_{}'.format(student_or_child, key)] = value
    return res

上面的函数将dict作为参数,对于传递的key, value中的每个dict,如果值是dict类型,则在值上调用相同的函数,并将结果添加到{ {1}} dict,否则会添加相同的值。

现在,使用list comprehension,我们可以:

res

<强>输出:

[new_dict(d) for d in students]