2009-12-11 38 views

Trả lời

42

Python dict s KHÔNG duy trì thứ tự trước 3.6.

Tuy nhiên, trường hợp của csv.DictReader mà bạn đang sử dụng (sau khi bạn đã đọc những dòng đầu tiên -!) không có một danh sách .fieldnames của chuỗi, mà theo thứ tự.

Vì vậy,

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

sẽ cho bạn thấy rằng trật tự thực sự là duy trì (trong .fieldnames tất nhiên, KHÔNG BAO GIỜ trong dict - đó là bản chất không thể bằng Python -!).

Vì vậy, giả sử bạn muốn đọc a.csv và viết b.csv với cùng thứ tự cột. Sử dụng trình đọc và ghi đơn giản là quá dễ dàng, vì vậy bạn muốn sử dụng các giống Dict thay thế ;-). Vâng, một cách là ...:

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() 

giả sử bạn có tiêu đề trong a.csv (otherewise bạn không thể sử dụng một DictReader vào nó) và muốn chỉ các tiêu đề tương tự trong b.csv.

+0

Cảm ơn Alex Martelli! Bạn đã đi qua và trên các cuộc gọi của nhiệm vụ ở đây :) và ... nó được đánh giá cao! Tôi đã không nhận ra có tên trường, nhưng đọc lại tài liệu API tôi có thể thấy ngay bây giờ. Cảm ơn bạn đã thay thế, nhưng kể từ khi DictReader của tôi hoạt động tốt, tôi sẽ gắn bó với nó. – Alex

+0

@RaffiKhatchadourian a là a.csv, b là b.csv có lẽ là viết tắt để đọc từ tập tin a, wb có lẽ để ghi vào tập tin b, d cho từ điển, dh cho tiêu đề từ điển .... Alex Cảm ơn lời giải thích tuyệt vời ! – Deep

+0

bất kỳ lý do nào tại sao bạn đi qua toàn bộ 'dh = dict (...' '... wb.writerow (dh)' khi bạn có thể thực hiện 'wb.fieldnames = ra.fieldnames; wb.writeheader()'? – Baldrickk

7
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

Tôi biết câu hỏi này là cũ ... nhưng nếu bạn sử dụng DictReader, bạn có thể vượt qua nó một danh sách đặt hàng với fieldnames đến fieldnames param

1

Unfortunatley mặc định DictReader không cho phép các trọng lớp dict, một DictReader tùy chỉnh sẽ làm các trick dù

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 

sử dụng nó như vậy

import collections 

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

Tạo một OrderedDict từ mỗi hàng dict được sắp xếp theo 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]))) 
Các vấn đề liên quan