Подтвердить что ты не робот

Можно ли сохранить порядок столбцов с помощью Python csv DictReader

Например, мои csv имеют столбцы, как показано ниже:

ID, ID2, дата, номер задания, код

Мне нужно записать столбцы в том же порядке. Диктат сразу же перепутал заказ, поэтому я считаю, что это больше проблема с читателем.

4b9b3361

Ответ 1

Python dict НЕ поддерживать порядок до 3.6.

Однако экземпляр csv.DictReader, который вы используете (после того, как вы прочитали первую строку!), имеет список строк .fieldnames, который IS по порядку.

Итак,

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

покажет вам, что порядок действительно поддерживается (в .fieldnames, конечно, НИКОГДА в dict), что по сути невозможно в Python! -).

Итак, предположим, что вы хотите прочитать a.csv и написать b.csv с тем же порядком столбцов. Использование простого читателя и писателя слишком просто, поэтому вместо этого вы хотите использовать разновидности Дикта;-). Ну, один из способов...:

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 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.

Ответ 2

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)

Ответ 3

Сделайте 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])))

Ответ 4

Я знаю, что этот вопрос старый... но если вы используете DictReader, вы можете передать ему упорядоченный список с именами полей в fieldnames param

Ответ 5

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)
# ...