在Python中合并字典值

时间:2014-01-21 10:28:09

标签: python dictionary

我有语言特定的词典遵循完全相同的数据结构只有使它们不同的是语言,请参阅下面的示例,

所以,基本上我有字典如下 的 INPUT

{
        'english': [
            {
                'id': "field_1",
                'label': "Items",
                'type': "choicefield",
                'choices': [
                    ["", "All Items"],
                    [0, "Item 0"],
                    [1, "Item 1"],
                    [2, "Item 2"]
                ]
            },
            {
                'id': "field_2",
                'label': "Keywords",
                'type': "textfield",
                'choices': None
            },
            {
                "id": "field_3",
                "label": "Agree?",
                "type": "checkbox",
                "choices": None
            },
        ],
        'french': [
            {
                'id': "field_1",
                'label': "Items (fr translated)",
                'type': "choicefield",
                'choices': [
                    ["", "All Items (fr translated)"],
                    [0, "Item 0 (fr translated)"],
                    [1, "Item 1 (fr translated)"],
                    [2, "Item 2 (fr translated)"]
                ]
            },
            {
                'id': "field_2",
                'label': "Keywords (fr translated)",
                'type': "textfield",
                'choices': None
            }
        ]
}

我想要的输出是以下结构中的API响应(基本上是合并语言/翻译字段),

预期输出

[
    {
        'id': "field_1",
        'label': {
            'english': "Items",
            'french': "Items (fr translated)",
        },
        'type': 'choicefield',
        'choices': [
            ["", {"english": "All Items", "french": "All Items (fr translated)"}],
            [0, {"english": "Item 0", "french": "Item 0 (fr translated)"}],
            [1, {"english": "Item 1", "french": "Item 1 (fr translated)"}],
            [2, {"english": "Item 2", "french": "Item 2 (fr translated)"}],
        ]
    },
    {
        'id': "field_2",
        'label': {
            'english': "Keywords",
            'french': "Keywords (fr translated)",
        },
        'type': 'textfield',
        'choices': []
    }
]

到目前为止所做的是

def merge_options(options_dict):
    from copy import deepcopy
    MERGE_FIELD_LIST = ['label']
    languages = options_dict.keys()
    data_copy = deepcopy(options_dict[languages[0]])
    for i, item in enumerate(data_copy):
        for field in MERGE_FIELD_LIST:
            field_dict = {}
            for lang in languages:
                try:
                    field_dict.update({lang: options_dict[lang][i][field]})
                except KeyError:
                    pass
            item.update({field: field_dict})
    return data_copy

实际上是期望的或字段"标签"但是我无法合并选项字段,编写的代码也非常难看而且不是pythonic的做法,寻找任何更好更快的方法来做到这一点。

谢谢

1 个答案:

答案 0 :(得分:2)

首先获取英文版本,然后合并其他语言:

# build initial structure with English labels
fields = [f.copy() for f in per_language['english']]
for field in fields:
    field['label'] = {'english': field['label']}
    if field['choices'] is not None:
        field['choices'] = [[id, {'english': label}] for id, label in field['choices']]

# copy in the translated labels
for language, language_fields in per_language.iteritems():
    if language == 'english': continue
    # assumption: fields are always listed in the same order
    for field, language_field in zip(fields, language_fields):
        field['label'][language] = language_field['label']
        if field['choices'] is not None:
            for (id, choice_labels), (_, language_label) in zip(field['choices'], language_field['choices']):
                choice_labels[language] = language_label

这会产生:

[{'choices': [['',
               {'english': 'All Items',
                'french': 'All Items (fr translated)'}],
              [0, {'english': 'Item 0', 'french': 'Item 0 (fr translated)'}],
              [1, {'english': 'Item 1', 'french': 'Item 1 (fr translated)'}],
              [2, {'english': 'Item 2', 'french': 'Item 2 (fr translated)'}]],
  'id': 'field_1',
  'label': {'english': 'Items', 'french': 'Items (fr translated)'},
  'type': 'choicefield'},
 {'choices': None,
  'id': 'field_2',
  'label': {'english': 'Keywords', 'french': 'Keywords (fr translated)'},
  'type': 'textfield'},
 {'choices': None,
  'id': 'field_3',
  'label': {'english': 'Agree?'},
  'type': 'checkbox'}]