【问题标题】:How to save list of dicts as CSV and keep keys in order?如何将字典列表保存为 CSV 并按顺序保存键?
【发布时间】:2020-01-31 10:32:03
【问题描述】:

我有一个字典列表,需要将它们保存为 CSV。第一行是标题列表字段名称。

字段顺序应与标题中的相同。问题是某些字段是可选的,而某些 dicts 不包含它们。另一个问题是 python 不会按照定义的顺序迭代 dict 键。

import csv
import sys

fields = ['first_name', 'last_name', 'city']

dicts = [
    {
        "first_name": "John",
        "last_name": "Doe",
        "city": "New York",
    },
    {
        "first_name": "Agent",
        "last_name": "Smith",
        "city": "Matrix",
    },
]

csv_writer = csv.writer(sys.stdout)

csv_writer.writerow(fields)

for obj in dicts:
    # fields order mismatch
    csv_writer.writerow(obj.values())

这会产生与标题不匹配的 CSV 行。

first_name, last_name, city
New York,   John,      Doe
Matrix,     Agent,     Smith

我可以手动对字段进行排序并检查缺失的项目,但我想知道是否有更好的解决方案可以按预定义的顺序将 dict 值输出到 CSV?

【问题讨论】:

  • 您使用的是哪个 Python 版本?这似乎是由于字典在 3.6 之前的 Python 版本上不保留键顺序。
  • 换行即可:csv_writer.writerow([ obj[key] for key in fields ])
  • 使用python 2.7
  • @aminrd,这不会解决问题,因为使用的 Python 版本不保留字典键顺序。 alex2007v 发布了正确答案。
  • @accdias 这就是为什么我正在阅读来自fields 列表的订单!

标签: python csv


【解决方案1】:

使用 DictWriter(您在 fieldnames 列表中也有错字:fisrt_name 而不是 firs强>t_name):

import csv
import sys

fieldnames = ['first_name', 'last_name', 'city']

dicts = [
    {
        "first_name": "John",
        "last_name": "Doe",
        "city": "New York",
    },
    {
        "first_name": "Agent",
        "last_name": "Smith",
        "city": "Matrix",
    },
]
writer = csv.DictWriter(sys.stdout, fieldnames=fieldnames)

writer.writeheader()
for row in dicts:
    writer.writerow(row)

【讨论】:

  • 这是问题中具体问题的正确答案。然而,更实际的一点是:(1) 最新版本的 Python (3.6+) 使用有序 dicts 作为标准,(2) 如果你使用 Pandas,这些东西总是更容易。
  • @ajrwhite,当标准库已经有一个解决问题的csv 模块时,没有理由为这么简单的任务推广pandas。
  • 在实际环境中,这个问题似乎不太可能没有其他方面来发挥 pandas 的功能。我只是在用实际的、真实的术语谈论——当然 csv 库对于所呈现的示例问题很好。
【解决方案2】:

接受的答案很好,它利用了 python 标准库csv。我只是把我的答案放在这里(使用pandas 方法)以防它可能对某人有所帮助。

In [12]: import pandas as pd

In [13]: dicts = [ 
    ...:     { 
    ...:         "first_name": "John", 
    ...:         "last_name": "Doe", 
    ...:         "city": "New York", 
    ...:     }, 
    ...:     { 
    ...:         "first_name": "Agent", 
    ...:         "last_name": "Smith", 
    ...:         "city": "Matrix", 
    ...:     }, 
    ...: ]                                                                                                                                                                                                         

In [14]: df = pd.DataFrame(dicts)                                                                                                                                                                                  

In [15]: df                                                                                                                                                                                                        
Out[15]: 
  first_name last_name      city
0       John       Doe  New York
1      Agent     Smith    Matrix

In [16]: df.to_csv("/path/to/save", index=False) # if you want to save

希望这会有所帮助。

【讨论】:

  • 对于这样一个简单的任务来说这太过分了:sys.getsizeof(pd.DataFrame) == 1064sys.getsizeof(csv.writer) == 80
  • @accdias 同意,这就是为什么我说接受的答案非常适合使用csv。但我认为如果有人需要pandas 解决方案来利用简单的数据操作等,将其放在这里很有用。
  • 很公平。顺便说一句,我也是熊猫的忠实粉丝。
猜你喜欢
  • 2021-07-04
  • 2012-04-29
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-20
相关资源
最近更新 更多