Search code examples
pythondictionarydictionary-comprehension

Dictionary Splitting/Comprehension


I have a dictionary I want to split into a list of dictionaries for adding submissions into a database.

Here is the dictionary, this is not a static dict, it would be dynamically generated, so numbers can increase:

# notice the keys are all grouped by numbers, 

 data = {'resident_payer,1': 'William Brown',
        'Term Fee,amount_paid,1': '1',
        'method,1': 'credit',
        'document_id,1': '1',

        'resident_payer,2': None,
        'Term Fee,amount_paid,2': '0',
        'method,2': 'other',
        'document_id,2': '0'}

I need a list of dictionaries that would look like this:

[
{'resident_payer': 'William Brown', 'Term Fee,amount_paid': '1', 'method': 'credit', 'document_id': '1'},
{'resident_payer': None, 'Term Fee_amount_paid': '0', 'method': 'other', 'document_id': '0'}
]

How can I do this in a simple way with a dict comprehension?

Here is working code, but I could not figure the solution out without what seems like strange complexity as I am using and clearing variables declared outside of my loop so I would like a more clear, pythonic way to write this.

data = {'resident_payer,1': 'William Brown',
        'Term Fee,amount_paid,1': '1',
        'method,1': 'credit',
        'document_id,1': '1',

        'resident_payer,2': None,
        'Term Fee,amount_paid,2': '0',
        'method,2': 'other',
        'document_id,2': '0'}

# will hold broken down lists
list_of_submissions = list()
# used to parse data into separated list of dictionaries.
# The key is split into numbers for grouping
current_loop = 1
active_dict_to_add_to_list = dict()
for key, value in data.items():
    if f'{current_loop}' in key:
        # we are in the current iteration
        # add the item to the active dict, the key is split by the ',' and [1] is the number so [0] needs to be selected
        # slice by 0: -1 to get first to everything but last element
        key_to_use = ",".join(key.split(',')[0:-1])

        active_dict_to_add_to_list[key_to_use] = value
        print(active_dict_to_add_to_list)
        # I know the dict should be 4 in length s I can realize I need to add here, but I don't like that...
        if len(active_dict_to_add_to_list) == 4:
            list_of_submissions.append(active_dict_to_add_to_list)
            # print('added', active_dict_to_add_to_list)
            active_dict_to_add_to_list = dict()
            current_loop += 1
    else:
        # we need to move to new iteration
        # add the current active dict to the list of submissions
        list_of_submissions.append(active_dict_to_add_to_list)
        print('added', active_dict_to_add_to_list)
        # clear the active dict so it can be added again
        active_dict_to_add_to_list = dict()
        current_loop += 1

print(list_of_submissions)


Solution

  • data = {'resident_payer,1': 'William Brown',
            'Term Fee,amount_paid,1': '1',
            'method,1': 'credit',
            'document_id,1': '1',
    
            'resident_payer,2': None,
            'Term Fee,amount_paid,2': '0',
            'method,2': 'other',
            'document_id,2': '0'}
    
    out = {}
    for k, v in data.items():
        # all but last element
        key_to_use = ",".join(k.split(',')[0:-1])
        out.setdefault(k.split(',')[-1], {})[key_to_use] = v
    
    out = list(out.values())
    
    print(out)
    

    Prints:

    [{'resident_payer': 'William Brown', 'Term Fee': '1', 'method': 'credit', 'document_id': '1'}, {'resident_payer': None, 'Term Fee': '0', 'method': 'other', 'document_id': '0'}]