【问题标题】:Python 3: Creating list of multiple dictionaries have same keys but different values coming from multiple listsPython 3:创建多个字典的列表具有相同的键但来自多个列表的不同值
【发布时间】:2020-05-20 23:01:55
【问题描述】:

我正在使用 lxml 库中的 xpath 解析 XML 的响应。 我正在获取结果并从中创建列表,如下所示:

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

我想使用列表为列表中的每个元素创建一个字典,然后将它们添加到最终列表中,如下所示:

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

我想要一个生成器,因为我将来可能需要从响应中搜索更多元数据,所以我希望我的代码能够面向未来并减少重复:

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

但是这个函数给了我这个:

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

我一直在论坛中寻找类似案例,但找不到符合我需求的案例。 感谢您的帮助。

更新: Renneys 的答案是我想要的,我只是调整了结果范围的长度值,因为每个对象键的 xpath 长度并不总是相同,而且我的列表具有相同的每次我选择第一个索引 [0] 时的长度。 现在函数看起来像这样。

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

【问题讨论】:

  • 我不明白,你为什么要单独的字典?
  • 所以我可以遍历每个 dict 来创建一个正文以在 elasticsearch 中进行索引

标签: python list dictionary dictionary-comprehension


【解决方案1】:

使用二维数组:

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

【讨论】:

  • 看起来不错但抛出错误:IndexError: list index out of range for line: add[keys[j]] = tmp[j][i]
  • 每个xpath数组的结果是否相同?那么“objectName”、“objectSize”……的值是否相同?如果没有,那就是这里的问题。唯一可能导致此错误的部分是 tmp[j][i],因为由于 j 和列表的定义方式,keys[j] 和 tmp[j] 存在。
  • 没有每个xpath列表的长度可以是任意数字。如果我得到 5 个结果而不是 2 个之前的结果,我明白你的意思。它匹配 tmp 和 add 数组的长度。但是,每个 xpath 可能会得到 5 个甚至 500,000 个结果。请注意,所有列表的长度都相同,例如:objectName length = objectSize length 等。可以修复吗?
  • 如果 len(tmp[j])
【解决方案2】:

我想这就是你要找的。​​p>

您可以使用 zip 将两个列表组合成一个值对列表。
然后,您可以使用列表推导式或生成器表达式将值对与所需的键配对。

import pprint

object_name = ['file1234', 'file5671']
object_size = [9347627, 9406875]

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

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

# List Comprehension
obj_list = [{'object_name': name, 'object_size': size} for name,size in zip(object_name,object_size)]

pprint.pprint(obj_list)
print('\n')


# Generator Expression
generator = ({'object_name': name, 'object_size': size} for name,size in zip(object_name,object_size))

for obj in generator:
  print(obj)

实时代码示例 -> https://onlinegdb.com/SyNSwd7jU


我认为接受的答案更有效,但这里有一个如何使用列表推导的示例。

meta_names = {
'object_name': ['file1234', 'file5671'],
'object_size_KB': ['9347627', '9406875'],
'object_text': ['Bob', 'Ross']
             }

def parse_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
  """
  # List comprehensions
  to_dict = lambda l: [{key:val for key,val in pairs} for pairs in l]

  objs = list(zip(*list([[key,val] for val in vals] for key,vals in meta_names.items())))

  pprint.pprint(to_dict(objs))  

parse_response(meta_names)

实时代码 -> https://onlinegdb.com/ryLq4PVjL

【讨论】:

  • 嗨,埃文,如果我事先不知道我的键并想将它们作为字典传递给函数,然后生成每个 xpath 的列表,然后得到最终列表,就像我的问题中的函数一样?注意键:object_name、object_size 不是我拥有的唯一键,它们可能比 object_status、object_deleted 等更多。
  • 啊,如果你想要另一个例子,我的新解决方案应该可以工作。
  • 谢谢埃文,看起来很扎实。但我也接受了@Rennney 的回答,因为他也解决了 xpath 匹配问题。所以我不需要使用 to 函数来实现我所需要的。感谢您回复另一个答案
猜你喜欢
  • 2014-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-18
  • 2021-10-10
  • 2011-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多