如何从 csv 构建嵌套有序字典?

How to build a nested ordered dict from a csv?

如何获得嵌套字典,其中键和子键的顺序与 csv 文件中的顺序精确相同?

我试过了

import csv
from collections import OrderedDict

filename = "test.csv"
aDict = OrderedDict()

with open(filename, 'r') as f:
    csvReader = csv.DictReader(f)
    for row in csvReader:
        key = row.pop("key")
        aDict[key] = row

其中 test.csv 看起来像

key,number,letter
eins,1,a
zwei,2,b
drei,3,c

但是子词典没有排序(行字母和数字改变了)。那么如何按顺序填充 aDict[key]

csv.DictReader 将行加载到常规 dict 而不是有序行中。您必须手动将 csv 读入 OrderedDict 以获得您需要的顺序:

from collections import OrderedDict

filename = "test.csv"
dictRows = []

with open(filename, 'r') as f:
    rows = (line.strip().split(',') for line in f)
    # read column names from first row
    columns = rows.next()
    for row in rows:
        dictRows.append(OrderedDict(zip(columns, row)))

这是一种方式:

import csv
from collections import OrderedDict

filename = "test.csv"
aDict = OrderedDict()

with open(filename, 'r') as f:
    order = next(csv.reader(f))[1:]
    f.seek(0)

    csvReader = csv.DictReader(f)
    for row in csvReader:
        key = row.pop("key")
        aDict[key] = OrderedDict((k, row[k]) for k in order)

您必须从 csv.reader 返回的行中自行构建字典和子字典,这些行是序列,而不是使用 csv.DictReader

幸运的是这很容易:

import csv
from collections import OrderedDict

filename = 'test.csv'
aDict = OrderedDict()

with open(filename, 'rb') as f:
    csvReader = csv.reader(f)
    fields = next(csvReader)
    for row in csvReader:
        temp = OrderedDict(zip(fields, row))
        key = temp.pop("key")
        aDict[key] = temp

import json  # just to create output
print(json.dumps(aDict, indent=4))

输出:

{
    "eins": {
        "number": "1",
        "letter": "a"
    },
    "zwei": {
        "number": "2",
        "letter": "b"
    },
    "drei": {
        "number": "3",
        "letter": "c"
    }
}

您可以利用现有 csv.DictReader class,但更改行 returns。为此,请将以下 class 添加到脚本的开头:

class OrderedDictReader(csv.DictReader):
    def next(self):
        # Get a row using csv.DictReader
        row = csv.DictReader.next(self)

        # Create a new row using OrderedDict
        new_row = OrderedDict(((k, row[k]) for k in self.fieldnames))
        return new_row

然后,使用 class 代替 csv.DictReader

csvReader = OrderedDictReader(f)

其余代码保持不变。