【发布时间】:2020-10-12 02:30:55
【问题描述】:
我收到了许多包含不同产品订单的 CSV 文件。这些 CSV 文件需要“转换”为特定的 JSON 结构。
CSV 文件的每一行代表一个产品的订单。这意味着如果我要订购两种产品,CSV 将包含两行。
CSV 文件的简化版本可能如下所示(请注意第一行和第三行中的orderId“111”):
orderId,itemNumber,itemName,name,street
111,123,testitem,john doe,samplestreet 1
222,345,anothertestitem,jane doe,samplestreet 1
111,345,anothertestitem,john doe,samplestreet 1
我当前的解决方案有效,但我认为我过于复杂了。
目前,我正在遍历每个 CSV 行并创建 JSON 结构,其中我使用一个辅助函数,该函数将添加订单或附加一个包含有序项目的列表,如下所示:
def add_orderitem(orderitem, order, all_orders):
""" Adds an ordered product to the order or "create" a new order if it doesn't exist """
for row in all_orders:
# Order already exists
if any(order["orderNumber"] == value for field, value in row.items()):
print(f"Order '{order['orderNumber']}' already exists, adding product #{orderitem['sku']}")
row["orderItems"].append(orderitem)
return all_orders
# New order
print(f"New Order found, creating order '{order['orderNumber']}' and adding product #{orderitem['sku']}")
all_orders.append(order)
order["orderItems"].append(orderitem)
return all_orders
def parse_orders():
""" Converts CSV-orders into JSON """
results = []
orders = read_csv("testorder.csv") # helper-function returns CSV-dictreader (list of dicts)
for order in orders:
# Create basic structure
orderdata = {
"orderNumber": order["orderId"],
"address": {
"name": order["orderId"],
"street": order["street"]
},
"orderItems": [] # <-- this will be filled later
}
# Extract product-information that will be inserted in above 'orderItems' list
product = {
"sku": order["itemNumber"],
"name": order["itemName"]
}
# Add order to final list or add item if order already exists
results = add_orderitem(product, orderdata, results)
return results
def main():
from pprint import pprint
parsed_orders = parse_orders()
pprint(parsed_orders)
if __name__ == "__main__":
main()
脚本工作正常,下面的输出是我所期待的:
New Order found, creating order '111' and adding product #123
New Order found, creating order '222' and adding product #345
Order '111' already exists, adding product #345
[{'address': {'name': '111', 'street': 'samplestreet 1'},
'orderItems': [{'name': 'testitem', 'sku': '123'},
{'name': 'anothertestitem', 'sku': '345'}],
'orderNumber': '111'},
{'address': {'name': '222', 'street': 'samplestreet 1'},
'orderItems': [{'name': 'anothertestitem', 'sku': '345'}],
'orderNumber': '222'}]
有没有办法“更聪明”地做到这一点?
【问题讨论】:
-
在
parse_orders中,results应该是defaultdict(list),以orderId作为键。 (即results[order["orderId"]].append(orderData))。目前,add_orderitem中的其他代码是多余的。 -
感谢您的提示!不幸的是,这会“复制”所有信息并为每个订购的产品添加一个全新的字典。我需要的是只在“orderItems”列表中添加产品,不复制其余数据
-
嗯,这让它变得更容易了。只需将
results设为普通的dict并添加orderData,前提是orderId不在results中。然后你可以简单地做results[order['orderId']]['orderItems'].append(product)。这只需要更改parse_orders中的 4 行代码(不计算缩进),并摆脱其他功能。这似乎是迄今为止最简单的解决方案,并且它具有返回一个结构的额外优势,该结构提供免费的 order-id 查找。
标签: python list csv dictionary