简体   繁体   English

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

[英]How to build a nested ordered dict from a csv?

How can I get a nested dictionary, where both the keys and the subkeys are precisely in the same order as in the csv file? 我怎样才能得到一个嵌套的字典,其中两个键和子键正是以相同的顺序为csv文件?

I tried 我试过了

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

where test.csv looks like 在哪里test.csv看起来像

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

But the sub-dictionaries are not ordered (rows letter and number are changed). 但是子词典没有排序(行字母和数字已更改)。 So how can I populate aDict[key] in an ordered manner? 那么如何以有序的方式填充aDict[key]

You have to build the dictionaries and sub-dictionaries yourself from rows returned from csv.reader which are sequences, instead of using csv.DictReader . 您必须自己从csv.reader返回的行(序列)构建字典和子字典,而不是使用csv.DictReader

Fortunately that's fairly easy: 幸运的是,这很容易:

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

Output: 输出:

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

This is one way: 这是一种方法:

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.DictReader loads the rows into a regular dict and not an ordered one. csv.DictReader将行加载到常规dict而不是有序dict You'll have to read the csv manually into an OrderedDict to get the order you need: 您必须手动将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)))

You can take advantage of the existing csv.DictReader class, but alter the rows it returns. 您可以利用现有的csv.DictReader类,但可以更改其返回的行。 To do that, add the following class to the beginning of your script: 为此,请将以下类添加到脚本的开头:

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

Then, use this class in place of csv.DictReader : 然后,使用此类代替csv.DictReader

csvReader = OrderedDictReader(f)

The rest of your code remains the same. 您的其余代码保持不变。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM