是否可以使用csv.DictReader保持列顺序?

时间:2009-12-11 01:41:11

标签: python csv

例如,我的csv包含以下列:

ID, ID2, Date, Job No, Code

我需要以相同的顺序写回列。 dict立即混淆了订单,所以我认为这对读者来说更是个问题。

5 个答案:

答案 0 :(得分:53)

Python的dict不维护3.6之前的顺序(但无论如何,在该版本中,csv.DictReader类被修改为返回OrderedDict s。。

但是,您正在使用的csv.DictReader实例(在您阅读完第一行之后! - )确实有一个.fieldnames字符串列表,其中 IS 按顺序排列。

所以,

for rowdict in myReader:
  print ['%s:%s' % (f, rowdict[f]) for f in myReader.fieldnames]

将向您显示订单确实已维护(当然,.fieldnamesdict中的 NEVER - 这在Python中本身是不可能的! - 。)。

因此,假设您要阅读a.csv并使用相同的列顺序编写b.csv。使用普通的读写器太容易了,所以你想使用Dict品种代替;-)。好吧,一种方法是......:

import csv

a = open('a.csv', 'r')
b = open('b.csv', 'w')
ra = csv.DictReader(a)
wb = csv.DictWriter(b, None)

for d in ra:

  if wb.fieldnames is None:
    # initialize and write b's headers
    dh = dict((h, h) for h in ra.fieldnames)
    wb.fieldnames = ra.fieldnames
    wb.writerow(dh)

  wb.writerow(d)

b.close()
a.close()

假设您在a.csv中有标题(或者您不能在其上使用DictReader)并且只需要b.csv中的相同标题。

答案 1 :(得分:8)

from csv import DictReader, DictWriter

with open("input.csv", 'r') as input_file:
    reader = DictReader(f=input_file)
    with open("output.csv", 'w') as output_file:
        writer = DictWriter(f=output_file, fieldnames=reader.fieldnames)
        for row in reader:
            writer.writerow(row)

答案 2 :(得分:6)

OrderedDict排序的每行dict制作DictReader.fieldnames

import csv
from collections import OrderedDict

reader = csv.DictReader(open("file.csv"))
for row in reader:
    sorted_row = OrderedDict(sorted(row.items(),
          key=lambda item: reader.fieldnames.index(item[0])))

答案 3 :(得分:2)

我知道这个问题已经过时了......但是如果您使用DictReader,则可以将带有字段名的有序列表传递给fieldnames param

答案 4 :(得分:2)

Unfortunatley默认的DictReader不允许覆盖dict类,但是自定义DictReader会执行这个技巧

import csv

class DictReader(csv.DictReader):
    def __init__(self, *args, **kwargs):
        self.dict_class = kwargs.pop(dict_class, dict)
        super(DictReader, self).__init__(*args, **kwargs)

    def __next__(self):
        ''' copied from python source '''
        if self.line_num == 0:
            # Used only for its side effect.
            self.fieldnames
        row = next(self.reader)
        self.line_num = self.reader.line_num

        # unlike the basic reader, we prefer not to return blanks,
        # because we will typically wind up with a dict full of None
        # values
        while row == []:
            row = next(self.reader)
        # using the customized dict_class
        d = self.dict_class(zip(self.fieldnames, row))
        lf = len(self.fieldnames)
        lr = len(row)
        if lf < lr:
            d[self.restkey] = row[lf:]
        elif lf > lr:
            for key in self.fieldnames[lr:]:
                d[key] = self.restval
        return d

像这样使用

import collections

csv_reader = DictReader(f, dict_class=collections.OrderedDict)
# ...