将Python对象嵌套到CSV

2024-09-30 20:24:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我查找了“嵌套dict”和“嵌套list”,但这两种方法都有效

我有一个结构如下的python对象:

    [{
    'id': 'productID1', 'name': 'productname A',
    'option': {
        'size': {
            'type': 'list',
            'name': 'size',
            'choices': [
                {'value': 'M'},
            ]}},

    'variant': [{
        'id': 'variantID1',
        'choices':
        {'size': 'M'},
        'attributes':
        {'currency': 'USD', 'price': 1}}]
}]

我需要输出以下扁平结构的csv文件:

id, productname, variantid, size, currency, price
productID1, productname A, variantID1, M, USD, 1
productID1, productname A, variantID2, L, USD, 2
productID2, productname A, variantID3, XL, USD, 3

我尝试了这个解决方案:Python: Writing Nested Dictionary to CSV 或者这个:From Nested Dictionary to CSV File

我去掉了[]周围和data内部的[],例如,我使用了来自2的这个代码片段,并根据我的需要对其进行了修改。IRL我无法摆脱[],因为调用API时得到的格式很简单

with open('productdata.csv', 'w', newline='', encoding='utf-8') as output:
    writer = csv.writer(output, delimiter=';', quotechar = '"', quoting=csv.QUOTE_NONNUMERIC)
    for key in sorted(data):
        value = data[key]
        if len(value) > 0:
            writer.writerow([key, value])
        else:
            for i in value:
                writer.writerow([key, i, value])

但是输出是这样的:

"id";"productID1"
"name";"productname A"
"option";"{'size': {'type': 'list', 'name': 'size', 'choices': {'value': 'M'}}}"
"variant";"{'id': 'variantID1', 'choices': {'size': 'M'}, 'attributes': {'currency': 'USD', 'price': 1}}"

有人能帮我吗

提前谢谢


Tags: csvkeynameidsizevaluepricecurrency
3条回答

列表索引必须是整数而不是字符串

下面是python列表的一个可视化示例:

0 carrot.
1 broccoli.
2 asparagus.
3 cauliflower.
4 corn.
5 cucumber.
6 eggplant.
7 bell pepper

012都是“指数”
"carrot""broccoli"等等。。。都被称为“值”

本质上,python list是一台具有整数输入和任意输出的机器

将python列表视为一个黑匣子:

  1. 一个数字,如5,进入框中
  2. 你转动一个附在盒子上的曲柄手柄
  3. 也许字符串"cucumber"是从盒子里出来的

您遇到了一个错误:TypeError: list indices must be integers or slices, not str

有各种各样的解决办法

将字符串转换为整数

将字符串转换为整数

listy_the_list = ["carrot", "broccoli", "asparagus", "cauliflower"]

string_index = "2"
integer_index = int(string_index)

element = listy_the_list[integer_index]

所以是的。。。。只要字符串标记看起来像数字(例如"456""7"),就可以使用该方法

整数类构造函数int()不是很聪明

例如,x = int("3 ")将产生一个错误

您可以尝试x = int(strying.strip())删除前导和尾随空格字符

使用允许键为字符串的容器

很久以前,在电子计算机出现之前,世界上有各种各样的集装箱:

  • 饼干罐
  • 松饼罐
  • 纸板箱
  • 玻璃罐
  • 钢罐
  • 背包
  • 行李袋
  • 衣柜/衣柜
  • 简案

在计算机编程中,还有各种类型的“容器”
如果不想,您不必使用list作为容器

在一些容器中,(也称为索引)可以是字符串,而不是整数

在python中,与列表类似但键/索引可以是字符串的标准容器是dictionary

thisdict = {
  "make": "Ford",
  "model": "Mustang",
  "year": 1964
}
thisdict["brand"] == "Ford"

如果要使用字符串而不是整数索引到容器中,请使用dict而不是list

以下是python dict的一个示例,该python以状态名称作为输入,以状态删节作为输出:

us_state_abbrev = {
    'Alabama': 'AL',
    'Alaska': 'AK',
    'American Samoa': 'AS',
    'Arizona': 'AZ',
    'Arkansas': 'AR',
    'California': 'CA',
    'Colorado': 'CO',
    'Connecticut': 'CT',
    'Delaware': 'DE',
    'District of Columbia': 'DC',
    'Florida': 'FL',
    'Georgia': 'GA',
    'Guam': 'GU',
    'Hawaii': 'HI',
    'Idaho': 'ID',
    'Illinois': 'IL',
    'Indiana': 'IN',
    'Iowa': 'IA',
    'Kansas': 'KS',
    'Kentucky': 'KY',
    'Louisiana': 'LA',
    'Maine': 'ME',
    'Maryland': 'MD',
    'Massachusetts': 'MA',
    'Michigan': 'MI',
    'Minnesota': 'MN',
    'Mississippi': 'MS',
    'Missouri': 'MO',
    'Montana': 'MT',
    'Nebraska': 'NE',
    'Nevada': 'NV',
    'New Hampshire': 'NH',
    'New Jersey': 'NJ',
    'New Mexico': 'NM',
    'New York': 'NY',
    'North Carolina': 'NC',
    'North Dakota': 'ND',
    'Northern Mariana Islands':'MP',
    'Ohio': 'OH',
    'Oklahoma': 'OK',
    'Oregon': 'OR',
    'Pennsylvania': 'PA',
    'Puerto Rico': 'PR',
    'Rhode Island': 'RI',
    'South Carolina': 'SC',
    'South Dakota': 'SD',
    'Tennessee': 'TN',
    'Texas': 'TX',
    'Utah': 'UT',
    'Vermont': 'VT',
    'Virgin Islands': 'VI',
    'Virginia': 'VA',
    'Washington': 'WA',
    'West Virginia': 'WV',
    'Wisconsin': 'WI',
    'Wyoming': 'WY'
}

以下是对我有效的最终解决方案:

data = [{
    'id': 'productID1', 'name': 'productname A',

    'variant': [{
        'id': 'variantID1',
        'choices':
        {'size': 'M'},
        'attributes':
        {'currency': 'USD', 'price': 1}},
        
        {'id':'variantID2',
        'choices':
        {'size': 'L'},
        'attributes':
        {'currency':'USD', 'price':2}}
        ]
},
{
    'id': 'productID2', 'name': 'productname B',

    'variant': [{
        'id': 'variantID3',
        'choices':
        {'size': 'XL'},
        'attributes':
        {'currency': 'USD', 'price': 3}},
        
        {'id':'variantID4',
        'choices':
        {'size': 'XXL'},
        'attributes':
        {'currency':'USD', 'price':4}}
        ]
}
]

for item in data:
    
        for variant in item['variant']:
            dic = {}
            dic.update (ProductID=item['id'])
            dic.update (Name=item['name'].title())
            dic.update (ID=variant['id'])
            dic.update (size=variant['choices']['size'])
            dic.update (Price=variant['attributes']['price'])
            
                
            products.append(dic)
          
keys = products[0].keys()

with open('productdata.csv', 'w', newline='', encoding='utf-8') as output_file:
    dict_writer = csv.DictWriter(output_file, keys,delimiter=';', quotechar = '"', quoting=csv.QUOTE_NONNUMERIC)
    dict_writer.writeheader()
    dict_writer.writerows(products)

具有以下输出:

"ProductID";"Name";"ID";"size";"Price"
"productID1";"Productname A";"variantID1";"M";1
"productID1";"Productname A";"variantID2";"L";2
"productID2";"Productname B";"variantID3";"XL";3
"productID2";"Productname B";"variantID4";"XXL";4

这正是我想要的

实际上,我可以迭代这个列表并创建自己的子列表,例如变体列表

data = [{
    'id': 'productID1', 'name': 'productname A',
    'option': {
        'size': {
            'type': 'list',
            'name': 'size',
            'choices': [
                {'value': 'M'},
            ]}},

    'variant': [{
        'id': 'variantID1',
        'choices':
        {'size': 'M'},
        'attributes':
        {'currency': 'USD', 'price': 1}}]
},
    {'id': 'productID2', 'name': 'productname B',
    'option': {
        'size': {
            'type': 'list',
            'name': 'size',
            'choices': [
                {'value': 'XL', 'salue':'XXL'},
            ]}},

    'variant': [{
        'id': 'variantID2',
        'choices':
        {'size': 'XL', 'size2':'XXL'},
        'attributes':
        {'currency': 'USD', 'price': 2}}]
    }

]

new_list = {}

for item in data:

    new_list.update(id=item['id'])
    new_list.update (name=item['name'])
    
    for variant in item['variant']:
        new_list.update (varid=variant['id']) 

        for vchoice in variant['choices']:
            new_list.update (vsize=variant['choices'][vchoice])    
                
        for attribute in variant['attributes']:
            new_list.update (vprice=variant['attributes'][attribute])            

    for option in item['option']['size']['choices']:
        new_list.update (osize=option['value'])            

print (new_list)

但是输出总是迭代的最后一项,因为我总是用update()覆盖新的_列表

{'id': 'productID2', 'name': 'productname B', 'varid': 'variantID2', 'vsize': 'XXL', 'vprice': 2, 'osize': 'XL'}

相关问题 更多 >