【问题标题】:Convert list to a dictionairy, then merge multiple dictionairies to one by key value将列表转换为字典,然后通过键值将多个字典合并为一个
【发布时间】:2020-02-14 19:16:41
【问题描述】:

我有三个 python 列表,我想将它们制作成一个字典,然后根据键值将这三个字典连接到一个字典中。

我的 python 列表是这样制作的:

with open ('full_product_shipments.xml','r') as file2:
    full_product_shipments = list([line.strip().replace('{"','').replace('}','').replace('"','').replace(':',',').split(',') for line in file2])

它们看起来像这样:

列表1

[['transaction_id', '224847627', 'product_amount', '2.73', 'user_invoice_date', '2018-12-21'],
['transaction_id', '67919397', 'product_amount', '2.73', 'user_invoice_date', '2017-10-26']]

list2

[['tracking_code', '29285908', 'from_country', 'FR', 'to_country', 'FR', 'package_type_id', '10', 'transaction_id', '172238850', 'shipping_label_created', '2018-09-25 18', '40', '52'],
['tracking_code', '22105784', 'from_country', 'FR', 'to_country', 'FR', 'package_type_id', '10', 'transaction_id', '111423825', 'shipping_label_created', '2018-04-13 11', '22', '44']]

列表3

[['tracking_code', '21703238', 'from_country', 'FR', 'to_country', 'FR', 'amount', '3.23'],
['tracking_code', '41545695', 'from_country', 'FR', 'to_country', 'FR', 'amount', '2.9']]

list1list2 都有transaction_id,一旦我将它们转换为字典,我就需要加入它们。

新加入的列表(list1list2)和list3都有tracking_id,我想通过它加入他们一次list3 被转换为字典。

我试过用这个:

result=[x.update(amount=y['amount']) for x in full_product_shipments for y in full_provider_invoices if x['transaction_id'] == y['transaction_id']]

但这会引发 TypeError:

TypeError: list indices must be integers or slices, not str

也许没有必要将所有内容都转换为 dict。我是 python 的新手,所以如果有更好的方法来基于键合并信息,我将不胜感激。

【问题讨论】:

  • full_product_shipmentsfull_provider_invoices 等是哪个列表?
  • 第一个列表是full_product_invoices,第二个列表是full_product_shipments,第三个列表是full_provider_invoices

标签: python list dictionary merge


【解决方案1】:

您的示例数据中的示例似乎没有匹配的条目,假设您的完整数据集将匹配您可以执行此类操作的所有内容。

l1 = [['transaction_id', '224847627', 'product_amount', '2.73', 'user_invoice_date', '2018-12-21'], ['transaction_id', '67919397', 'product_amount', '2.73', 'user_invoice_date', '2017-10-26']]
l2 = [['tracking_code', '29285908', 'from_country', 'FR', 'to_country', 'FR', 'package_type_id', '10', 'transaction_id', '172238850', 'shipping_label_created', '2018-09-25 18', '40', '52'], ['tracking_code', '22105784', 'from_country', 'FR', 'to_country', 'FR', 'package_type_id', '10', 'transaction_id', '111423825', 'shipping_label_created', '2018-04-13 11', '22', '44']]
l3 = [['tracking_code', '21703238', 'from_country', 'FR', 'to_country', 'FR', 'amount', '3.23'], ['tracking_code', '41545695', 'from_country', 'FR', 'to_country', 'FR', 'amount', '2.9']]

# Convert everything to dict
result = {y['transaction_id']:y for y in [dict(zip(x[::2], x[1::2])) for x in l1]}
d2 = {y['transaction_id']:y for y in [dict(zip(x[::2], x[1::2])) for x in l2]}
d3 = {y['tracking_code']:y for y in [dict(zip(x[::2], x[1::2])) for x in l3]}

# Update result dict with data from the other lists.
for entry in result.values():
    entry.update(d2[entry['transaction_id']])
    entry.update(d3[entry['tracking_code']])

【讨论】:

  • 谢谢你,成功了。我看到transaction_id 值是键,值是字典部分{...'amount': '2.9'}, '131734284': {'transaction_id': '131734284', 'product_amount': '2.73', 'user_invoice_date': '2018-06-14', 'tracking_code': '24503936', 'from_country': 'FR', 'to_country': 'FR', 'package_type_id': '11', 'shipping_label_created': '2018-06-07 09', '51': '45', 'amount': '2.9'} 的其余部分。我将如何遍历值键?例如,如果我想获取所有产品金额或 from_country 值?什么时候所有的信息都已经被赋予了价值?
  • 您可以像for v in result.values(): 这样遍历值,然后v 将包含每个事务字典,然后您可以索引到v['product_amount'] 以获取特定值。
【解决方案2】:

如果原始原始数据是“json”格式而不是“xml”格式,这将更容易加入。如果您使用 REST API 下载数据,请尝试在末尾传入一个关键字 '&$format=json' 并查看文件结果是否以 json 字符串的形式返回。例如,这将在 SAP REST API 中工作,但我认为这是许多 API 提供者中的标准参数。

为了分享我在工作中的经历,我得到了一个默认响应为 XML 的 SAP API……我尝试使用 Python XML 解析库来理解它(我的大脑无休止地绞尽脑汁),直到我意识到我可以通过原始 URL 字符串的参数,它会以 JSON 形式返回。根据我的经验,这是我对您的问题的建议。

这是一个带有语法的公共 API 示例……尝试为您的 API 尝试类似的组合。

https://vpic.nhtsa.dot.gov/api/

https://vpic.nhtsa.dot.gov/api/Home/Index/LanguageExamples

现在,如果您可以下载 JSON 字符串,那么将其转换为 Python 字典非常容易……网上有很多资源可以做到这一点。然后从 Python 字典转换为 pandas 数据框很简单,网上有很多资源如何做到这一点。然后将多个数据框连接在一起很简单,网上有很多资源如何做到这一点。

如果您无法获得 JSON 字符串,有一些(更复杂的)在线资源介绍了如何从 XML 转换为 JSON。这里有几个链接:

How to convert an xml string to a dictionary?

https://ericscrivner.me/2015/07/python-tip-convert-xml-tree-to-a-dictionary/

http://code.activestate.com/recipes/573463-converting-xml-to-dictionary-and-back/

您会发现使用字典比使用列表要容易得多。列表旨在存储有序项目,但您的列表存储了一堆键值对(这正是字典的用处)。

希望有帮助!

【讨论】:

  • 谢谢,会看看!
【解决方案3】:

看起来,尽管是 xml 文件名,但您的源是 JSON,正如另一个响应中提到的那样,从 JSON 生成字典可能更容易。

假设不可能,下面的程序将遍历你的不同列表,尝试获取一个事务 id,它将用作我们的主 defaultdict 的 key,如果 id 没有,它将填充一个空 dict' t 存在或在其字典中附加一个新条目。

这是完整的代码。请注意,我已将第二个列表修改为具有与第一个列表匹配的 id,以显示如何将来自不同列表的字段合并到同一个字典中。这假定字段之间没有重叠。

from collections import defaultdict

list1 = [['transaction_id', '224847627', 'product_amount', '2.73', 'user_invoice_date', '2018-12-21'],
['transaction_id', '67919397', 'product_amount', '2.73', 'user_invoice_date', '2017-10-26']]

# list2 = [['tracking_code', '29285908', 'from_country', 'FR', 'to_country', 'FR', 'package_type_id', '10', 'transaction_id', '172238850', 'shipping_label_created', '2018-09-25 18', '40', '52'],
list2 = [['tracking_code', '29285908', 'from_country', 'FR', 'to_country', 'FR', 'package_type_id', '10', 'transaction_id', '224847627', 'shipping_label_created', '2018-09-25 18', '40', '52'],
['tracking_code', '22105784', 'from_country', 'FR', 'to_country', 'FR', 'package_type_id', '10', 'transaction_id', '111423825', 'shipping_label_created', '2018-04-13 11', '22', '44']]

list3 = [['tracking_code', '21703238', 'from_country', 'FR', 'to_country', 'FR', 'amount', '3.23'],
['tracking_code', '41545695', 'from_country', 'FR', 'to_country', 'FR', 'amount', '2.9']]




def aggregate_lists(*lists):
    transactions = defaultdict(dict)

    for list in lists:
        for row in list:
            try:
                id_col = row.index('transaction_id')
                transaction_id = row[id_col + 1]
            except ValueError:
                continue # Better error handling to be added.

            for col in range(0, len(row), 2):
                if col != id_col:
                    transactions[transaction_id][row[col]] = row[col + 1]

    return transactions

def main():
    transactions = aggregate_lists(list1, list2, list3)
    for k, props in transactions.items():
        print(f'Transaction: {k}')
        for k, v in props.items():
            print(f'\t{k}: {v}')

if __name__ == '__main__':
    main()

这是给定的输出:

Transaction: 224847627
    product_amount: 2.73
    user_invoice_date: 2018-12-21
    tracking_code: 29285908
    from_country: FR
    to_country: FR
    package_type_id: 10
    shipping_label_created: 2018-09-25 18
    40: 52
Transaction: 67919397
    product_amount: 2.73
    user_invoice_date: 2017-10-26
Transaction: 111423825
    tracking_code: 22105784
    from_country: FR
    to_country: FR
    package_type_id: 10
    shipping_label_created: 2018-04-13 11
    22: 44

我刚刚意识到 list3 没有事务 id,因此被忽略了。无论如何,这应该给出想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    相关资源
    最近更新 更多