2015-03-13 124 views
4

我有一个CSV文件,我已经过滤到列表中并进行了分组。例如:Python - 嵌套字典。错误在哪里?

 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': []} 

任何想法?

+1

为什么downvote它,然后留下任何解释?答案简单吗? – 2015-03-13 15:21:33

+1

'价值'的内容是什么? – Matthias 2015-03-13 15:24:52

+0

@Matthias只是列表的索引。在这种情况下,整数6.我试图用6替换值。没有运气。 – 2015-03-13 15:30:58

回答

2

的问题是,你的内心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中给出的准则。它还建议仅将CamelCase用于类名称,而不用于变量名称,如FilteredTable1 - 但我没有更改。

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这样做。

+0

谢谢!非常感谢 – 2015-03-16 09:38:25

1

我张贴这种跟进和扩大我的previous answer

对于初学者来说,可以通过无需检查已有的条目简单地使字典中创建一个collections.defaultdictdict子类,而不是常规的一个精简代码远一点:

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] 
+0

感谢您的跟进。我之前没有遇到过defaultdict。非常有用的知道。 – 2015-03-17 10:12:21