Search code examples
pythonlistdictionarydictionary-comprehension

Python 3: Creating list of multiple dictionaries have same keys but different values coming from multiple lists


I'm parsing through a response of XML using xpath from lxml library. I'm getting the results and creating lists out of them like below:

object_name = [o.text for o in response.xpath('//*[name()="objectName"]')]
object_size_KB = [o.text for o in response.xpath('//*[name()="objectSize"]')]

I want to use the lists to create a dictionary per element in list and then add them to a final list like this:

[{'object_name': 'file1234', 'object_size_KB': 9347627},
{'object_name': 'file5671', 'objeobject_size_KBt_size': 9406875}]

I wanted a generator because I might need to search for more metadata from the response in the future so I want my code to be future proof and reduce repetition:

meta_names = {
'object_name': '//*[name()="objectName"]',
'object_size_KB': '//*[name()="objectSize"]'
             }
def parse_response(response, meta_names):
"""
input: response: api xml response text from lxml xpath
input: meta_names: key names used to generate dictionary per object
return: list of objects dictionary
"""
    mylist = []
   # create list of each xpath match assign them to variables
    for key, value in meta_names.items():
        mylist.append({key: [o.text for o in response.xpath(value)]})
    return mylist

However the function gives me this:

[{'object_name': ['file1234', 'file5671']}, {'object_size_KB': ['9347627', '9406875']}]

I've been searching for a similar case in the forums but couldn't find something to match my needs. Appreciate your help.

UPDATE: Renneys answer was what I wanted I just adjusted the length value of range of my results since I don't always have the same length of xpath per object key and since my lists have identical length everytime I picked first index [0]. now the function looks like this.

def create_entries(root, keys):
    tmp = []
    for key in keys:
        tmp.append([o.text for o in root.xpath('//*[name()="' + key + '"]')])
    ret = []
    # print(len(tmp[0]))
    for i in range(len(tmp[0])):
        add = {}
        for j in range(len(keys)):
            add[keys[j]] = tmp[j][i]
        ret.append(add)
    return ret

Solution

  • Use a two dimensional array:

    def createEntries(root, keys):
        tmp = []
        for key in keys:
            tmp.append([o.text for o in root.xpath('//*[name()="' + key + '"]')])
        ret = []
        for i in range(len(tmp)):
            add = {}
            for j in range(len(keys)):
                add[keys[j]] = tmp[j][i]
            ret.append(add)
        return ret