Adeel
Adeel

Reputation: 781

Merging dictionary values inPython

I have language specific dictionaries follow exactly same data structure only thing make them different is language, see the example below,

So, Basically I have dictionary as follow 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
            }
        ]
}

And what I want as output is API response in following structure (which is basically merged language/translated fields),

EXPECTED OUTPUT

[
    {
        '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': []
    }
]

what is have done so far is

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

Which actually gives be desired or field "label" but I am unable to merge options field, also the code written is very ugly and not pythonic way of doing, looking any better and faster approach to do that.

Thanks

Upvotes: 0

Views: 113

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121972

Grab the English version first, then merge in the other languages:

# 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

This produces:

[{'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'}]

Upvotes: 2

Related Questions