【问题标题】:Nested Python Object to CSV将 Python 对象嵌套到 CSV
【发布时间】:2021-05-07 03:23:29
【问题描述】:

我查找了“嵌套字典”和“嵌套列表”,但任何一种方法都有效。

我有一个具有以下结构的 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 的代码 sn-p 并根据我的需要进行了调整。 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}}"

有人可以帮帮我吗?

提前致谢

【问题讨论】:

  • 你能告诉我们你写了什么引发了错误吗?
  • 是的,我添加了使用的代码和错误
  • 要么您对实际引发错误的位置感到困惑(根据您的代码,它应该位于data[sessionId]),要么您发布的代码不完整
  • @c.Nivs 是的,你是对的,data 周围有[ ],会在data[sessionId] 产生错误。我删除了[ ] 并在writer.writerow([sessionId, item, ratings[item]]) 得到它。
  • @C.Nivs 我对其进行了一些调整,但输出仍然不令人满意... ^^ 和 IRL 我无法摆脱[ ] 因为这就是我从中得到的API 调用。

标签: python list csv dictionary nested


【解决方案1】:

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

下面是一个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 作为您的容器。

在某些容器中,(AKA 索引)可以是字符串,而不是整数.

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

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

如果您想使用字符串而不是整数来索引容器,请使用dict,而不是list

以下是 python dict 的示例,其中状态名称作为输入,状态缩写作为输出:

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'
}

【讨论】:

  • 您好,感谢您的回复,请查看我的编辑。我通过不使用字符串索引索引列表来消除该类型错误。但是,输出仍然不令人满意.. IRL 我无法摆脱[ ],因为那是我从 API 调用中得到的。
  • @boese 如果您的代码有多个问题,您应该在 stackoverflow.com 上将每个问题作为单独的问题发布。这个想法是,当人们在谷歌上搜索一些东西时,比如“UnicodeEncodeError:'ascii'编解码器无法编码字符”。如果您重新编写堆栈溢出问题以修复错误,那么没有其他人可以从您的错误中吸取教训。堆栈溢出的目的是从其他程序员的错误中吸取教训。如果您的代码中有第二个错误,请发布有关该特定错误的新问题;不要重写原来的问题。
  • @boese 理想情况下,每个堆栈溢出问题只讨论一个特定错误。您需要将程序中的错误分解为单独的部分。分别发布每个错误。理想情况下,您将尽可能多地删除程序中的代码,这样您仍然会收到相同的错误消息。简化您的代码,以便创建相同的错误,但代码更易于阅读。然后,您将在 stack-overflow.com 上发布简短的 sn-p
  • 这正是我发布最终解决方案的原因。实际上,该错误不是问题的一部分。但感谢您的游览。
【解决方案2】:

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

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() 覆盖 new_list。

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

【讨论】:

    【解决方案3】:

    这是对我有用的最终解决方案:

    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
    

    这正是我想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-29
      • 2016-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多