Search code examples
pythonlistdictionarylist-comprehensiondictionary-comprehension

Creating a list of dictionaries with numerous key value pairs


I have multiple lists that I need to combine into a list of dictionaries with multiple key value pairs wherein the value could in itself contain a list - so for example:

namesIDs = [1, 2, 3, 4, 5]
namesList = ['jacksparrow', 'aragron', 'harrypotter', 'bilbo', 'einstein']
address = ['addr1', 'addr2', 'addr3', 'addr4', 'addr5']
parentsIDs = [11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44, 51, 52, 53, 54, 55, 56] 
parentsNames = ['Teague', 'MrsT', 'gPaT', 'gMaT', 'Arathorn', 'Gilraen', 'gPaAg', 'gMaAg', 'James', 'Lily', 'gPaHp', 'gMaHp', 'Bungo', 'Belladona', 'gPaB', 'gMaB', 'Herman', 'Pauline', 'Abraham', 'Helene', 'babyA', 'babyB']

The output I'm expecting is:

[{'nameIDs': 1, 'namesList': 'jacksparrow', 'address': 'addr1', 'parentsIDs': [11,12,13,14], 'parentsNames': ['Teague', 'MrsT', 'gPaT', 'gMaT']},
 {'nameIDs': 2, 'namesList': 'aragorn', 'address': 'addr2', 'parentsIDs': [21,22,23,24], 'parentsNames': ['Arathorn', 'Gilraen', 'gPaAg', 'gMaAg']},
 {'nameIDs': 3, 'namesList': 'harrypotter', 'address': 'addr3', 'parentsIDs': [31,32,33,34], 'parentsNames': ['James', 'Lily', 'gPaHp', 'gMaHp']},
 {'nameIDs': 4, 'namesList': 'bilbo', 'address': 'addr4', 'parentsIDs': [41,42,43,44], 'parentsNames': ['Bungo', 'Belladona', 'gPaB', 'gMaB']},
 {'nameIDs': 5, 'namesList': 'einstein', 'address': 'addr5', 'parentsIDs': [51,52,53,54,55,56], 'parentsNames': ['Bungo', 'Belladona', 'gPaB', 'gMaB', 'babyA', 'babyB']}
]

NOTICE the last item parentsIDs/parentsNames are LONGER than the rest. I've tried using zip and dict comprehension but it doens't work/make sense to me.

>>> namesIDs = [1, 2, 3, 4, 5]
>>> namesList = ['jacksparrow', 'aragron', 'harrypotter', 'bilbo', 'einstein']
>>> [dict(zip(('NameID', 'Name'), item )) for item in namesList]
[{'NameID': 'j', 'Name': 'a'}, {'NameID': 'a', 'Name': 'r'}, {'NameID': 'h', 'Name': 'a'}, {'NameID': 'b', 'Name': 'i'}, {'NameID': 'e', 'Name': 'i'}]

EDIT: PLEASE note that parentsIDs and parentsNames might be arbitrarily long. The first digit of parentsID determines which nameID a parentsID correspond to.


Solution

  • You can use list slicing inside the following list comprehension.

    parentsIDsLists = [[]]
    parentsNamesLists = [[]]
    for i,j in zip(map(str, parentsIDs), parentsNames):
        if parentsIDsLists[-1] != [] and i[0] != parentsIDsLists[-1][-1][0]:
            parentsIDsLists.append([])
            parentsNamesLists.append([])
        parentsIDsLists[-1].append(i)
        parentsNamesLists[-1].append(j)
    
    out = [dict(zip(('nameIDs', 'namesList', 'address', 'parentsIDs', 'parentsNames'), tpl[:-2]+(list(map(int,tpl[-2])),)+(tpl[-1],))) 
           for tpl in zip(namesIDs, namesList, address, parentsIDsLists, parentsNamesLists)]
    

    Output:

    [{'nameIDs': 1,
      'namesList': 'jacksparrow',
      'address': 'addr1',
      'parentsIDs': [11, 12, 13, 14],
      'parentsNames': ['Teague', 'MrsT', 'gPaT', 'gMaT']},
     {'nameIDs': 2,
      'namesList': 'aragron',
      'address': 'addr2',
      'parentsIDs': [21, 22, 23, 24],
      'parentsNames': ['Arathorn', 'Gilraen', 'gPaAg', 'gMaAg']},
     {'nameIDs': 3,
      'namesList': 'harrypotter',
      'address': 'addr3',
      'parentsIDs': [31, 32, 33, 34],
      'parentsNames': ['James', 'Lily', 'gPaHp', 'gMaHp']},
     {'nameIDs': 4,
      'namesList': 'bilbo',
      'address': 'addr4',
      'parentsIDs': [41, 42, 43, 44],
      'parentsNames': ['Bungo', 'Belladona', 'gPaB', 'gMaB']},
     {'nameIDs': 5,
      'namesList': 'einstein',
      'address': 'addr5',
      'parentsIDs': [51, 52, 53, 54, 55, 56],
      'parentsNames': ['Herman', 'Pauline', 'Abraham', 'Helene', 'babyA', 'babyB']}]