Python - 嵌套字典。错误在哪里?
Python - nested dictionary. Where is the bug?
我有一个 CSV 文件,我已将其过滤到列表中并分组。示例:
52713
['52713', '', 'Vmax', '', 'Start Value', '', '\n']
['52713', '', 'Vmax', '', 'ECNumber', '1.14.12.17', '\n']
['52713', 'O2', 'Km', 'M', 'Start Value', '3.5E-5', '\n']
['52713', 'O2', 'Km', 'M', 'ECNumber', '1.14.12.17', '\n']
52714
['52714', '', 'Vmax', '', 'Start Value', '', '\n']
['52714', '', 'Vmax', '', 'ECNumber', '1.14.12.17', '\n']
['52714', 'O2', 'Km', 'M', 'Start Value', '1.3E-5', '\n']
['52714', 'O2', 'Km', 'M', 'ECNumber', '1.14.12.17', '\n']
据此,我创建了一个具有以下结构的嵌套字典:
dict = ID number:{Km:n, Kcat:n, ECNumber:n}
...对于列表中的每个 ID。
我使用下面的代码来创建这个字典
dict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print subitem
dict[subitem[EntryID]] = {}
dict[subitem[EntryID]]['EC'] = []
dict[subitem[EntryID]]['Km'] = []
dict[subitem[EntryID]]['Kcat'] = []
if 'ECNumber' in subitem:
dict[subitem[EntryID]]['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
dict[subitem[EntryID]]['Km'] = subitem[value]
#print subitem
这适用于 ECNumber 值,但不适用于 Km 值。它可以打印该行,表明它识别 Km 值存在,但没有将其放入字典中。
示例输出:
{'Km': [], 'EC': '1.14.12.17', 'Kcat': []}
有什么想法吗?
本
问题是您的内部 for
循环不断重新初始化 dict[subitem[EntryID]]
,即使它可能已经存在。通过显式检查它是否已经存在,已在以下内容中修复:
dict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print ' ', subitem
if subitem[EntryID] not in dict:
dict[subitem[EntryID]] = {}
dict[subitem[EntryID]]['EC'] = []
dict[subitem[EntryID]]['Km'] = []
dict[subitem[EntryID]]['Kcat'] = []
if 'ECNumber' in subitem:
dict[subitem[EntryID]]['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
dict[subitem[EntryID]]['Km'] = subitem[value]
#print subitem
但是,可以通过使用类似以下的内容来提高此代码的效率,从而避免重新计算值和双重字典查找。它也不使用内置类型的名称作为变量名称,这违反了 PEP8 - Style Guide for Python Code 中给出的指导方针。它还建议仅对 class 名称使用 CamelCase,而不对 FilteredTable1
这样的变量名称使用 CamelCase——但我没有改变它。
adict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print ' ', subitem
entry_id = subitem[EntryID]
if entry_id not in adict:
adict[entry_id] = {'EC': [], 'Km': [], 'Kcat': []}
entry = adict[entry_id]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]
#print subitem
实际上,由于您正在构建字典的字典,因此不清楚使用 groupby
这样做是否有任何优势。
我将此发布以跟进并扩展我的 。
对于初学者,您可以通过消除检查预先存在的条目的需要来进一步简化代码,只需将正在创建的字典创建为 collections.defaultdict
dict
子类而不是常规子类:
from collections import defaultdict
adict = defaultdict(lambda: {'EC': [], 'Km': [], 'Kcat': []})
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
for subitem in items:
entry = adict[subitem[EntryID]]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]
其次,正如我在另一个答案中提到的,我认为使用 itertools.groupby()
执行此操作不会给您带来任何好处 — 除了使过程比需要的更复杂。这是因为基本上你正在做的是制作一个字典的字典,其条目都可以随机访问,所以在这样做之前麻烦地对它们进行分组是没有好处的。下面的代码证明了这一点(结合使用如上所示的 defaultdict
):
adict = defaultdict(lambda: {'EC': [], 'Km': [], 'Kcat': []})
for subitem in FilteredTable1[1:]:
entry = adict[subitem[EntryID]]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]
我有一个 CSV 文件,我已将其过滤到列表中并分组。示例:
52713
['52713', '', 'Vmax', '', 'Start Value', '', '\n']
['52713', '', 'Vmax', '', 'ECNumber', '1.14.12.17', '\n']
['52713', 'O2', 'Km', 'M', 'Start Value', '3.5E-5', '\n']
['52713', 'O2', 'Km', 'M', 'ECNumber', '1.14.12.17', '\n']
52714
['52714', '', 'Vmax', '', 'Start Value', '', '\n']
['52714', '', 'Vmax', '', 'ECNumber', '1.14.12.17', '\n']
['52714', 'O2', 'Km', 'M', 'Start Value', '1.3E-5', '\n']
['52714', 'O2', 'Km', 'M', 'ECNumber', '1.14.12.17', '\n']
据此,我创建了一个具有以下结构的嵌套字典:
dict = ID number:{Km:n, Kcat:n, ECNumber:n}
...对于列表中的每个 ID。
我使用下面的代码来创建这个字典
dict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print subitem
dict[subitem[EntryID]] = {}
dict[subitem[EntryID]]['EC'] = []
dict[subitem[EntryID]]['Km'] = []
dict[subitem[EntryID]]['Kcat'] = []
if 'ECNumber' in subitem:
dict[subitem[EntryID]]['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
dict[subitem[EntryID]]['Km'] = subitem[value]
#print subitem
这适用于 ECNumber 值,但不适用于 Km 值。它可以打印该行,表明它识别 Km 值存在,但没有将其放入字典中。
示例输出:
{'Km': [], 'EC': '1.14.12.17', 'Kcat': []}
有什么想法吗?
本
问题是您的内部 for
循环不断重新初始化 dict[subitem[EntryID]]
,即使它可能已经存在。通过显式检查它是否已经存在,已在以下内容中修复:
dict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print ' ', subitem
if subitem[EntryID] not in dict:
dict[subitem[EntryID]] = {}
dict[subitem[EntryID]]['EC'] = []
dict[subitem[EntryID]]['Km'] = []
dict[subitem[EntryID]]['Kcat'] = []
if 'ECNumber' in subitem:
dict[subitem[EntryID]]['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
dict[subitem[EntryID]]['Km'] = subitem[value]
#print subitem
但是,可以通过使用类似以下的内容来提高此代码的效率,从而避免重新计算值和双重字典查找。它也不使用内置类型的名称作为变量名称,这违反了 PEP8 - Style Guide for Python Code 中给出的指导方针。它还建议仅对 class 名称使用 CamelCase,而不对 FilteredTable1
这样的变量名称使用 CamelCase——但我没有改变它。
adict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print ' ', subitem
entry_id = subitem[EntryID]
if entry_id not in adict:
adict[entry_id] = {'EC': [], 'Km': [], 'Kcat': []}
entry = adict[entry_id]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]
#print subitem
实际上,由于您正在构建字典的字典,因此不清楚使用 groupby
这样做是否有任何优势。
我将此发布以跟进并扩展我的
对于初学者,您可以通过消除检查预先存在的条目的需要来进一步简化代码,只需将正在创建的字典创建为 collections.defaultdict
dict
子类而不是常规子类:
from collections import defaultdict
adict = defaultdict(lambda: {'EC': [], 'Km': [], 'Kcat': []})
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
for subitem in items:
entry = adict[subitem[EntryID]]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]
其次,正如我在另一个答案中提到的,我认为使用 itertools.groupby()
执行此操作不会给您带来任何好处 — 除了使过程比需要的更复杂。这是因为基本上你正在做的是制作一个字典的字典,其条目都可以随机访问,所以在这样做之前麻烦地对它们进行分组是没有好处的。下面的代码证明了这一点(结合使用如上所示的 defaultdict
):
adict = defaultdict(lambda: {'EC': [], 'Km': [], 'Kcat': []})
for subitem in FilteredTable1[1:]:
entry = adict[subitem[EntryID]]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]