[英]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.