2016-06-27 61 views
1

我需要創建一個查找表來存儲表格數據並根據多個字段值檢索記錄。從namedtuple記錄結構檢索數據失敗

我找到了一個例子post # 15418386,它幾乎可以滿足我的需求,但它總是返回相同的記錄,無論傳遞的參數如何。 我在這篇文章的底部列出了代碼,casr鏈接不起作用。

我已驗證文件是否正確讀取,並且正在使用IDE中的調試器(使用PyCharm的Im)正確填充數據表。

在代碼中包含的測試數據是:

name,age,weight,height 
Bob Barker,25,175,6ft 2in 
Ted Kingston,28,163,5ft 10in 
Mary Manson,27,140,5ft 6in 
Sue Sommers,27,132,5ft 8in 
Alice Toklas,24,124,5ft 6in 

的函數總是返回最後一個記錄,我相信這個問題是在這幾行代碼。但我不明白它是如何工作的。

matches = [self.records[index] 
      for index in self.lookup_tables[field].get(value, []) ] 
return matches if matches else None 

我想明白代碼是如何工作,所以我可以編輯它能夠在多個參數進行搜索。

原始代碼:

from collections import defaultdict, namedtuple 
import csv 
class DataBase(object): 
    def __init__(self, csv_filename, recordname): 
     # read data from csv format file int list of named tuples 
     with open(csv_filename, 'rb') as inputfile: 
      csv_reader = csv.reader(inputfile, delimiter=',') 
      self.fields = csv_reader.next() # read header row 
      self.Record = namedtuple(recordname, self.fields) 
      self.records = [self.Record(*row) for row in csv_reader] 
      self.valid_fieldnames = set(self.fields) 
     # create an empty table of lookup tables for each field name that maps 
     # each unique field value to a list of record-list indices of the ones 
     # that contain it. 
     self.lookup_tables = defaultdict(lambda: defaultdict(list)) 

    def retrieve(self, **kwargs): 
     """Fetch a list of records with a field name with the value supplied 
      as a keyword arg (or return None if there aren't any).""" 

     if len(kwargs) != 1: 
      raise ValueError(
      'Exactly one fieldname/keyword argument required for function ' 
      '(%s specified)' % ', '.join([repr(k) for k in kwargs.keys()]) 
      ) 

     field, value = kwargs.items()[0]  # get only keyword arg and value 
     if field not in self.valid_fieldnames: 
      raise ValueError('keyword arg "%s" isn\'t a valid field name' % field) 
     if field not in self.lookup_tables:  # must create field look up table 
      for index, record in enumerate(self.records): 
       value = getattr(record, field) 
       self.lookup_tables[field][value].append(index) 

     matches = [self.records[index] 
        for index in self.lookup_tables[field].get(value, []) ] 
     return matches if matches else None 


if __name__ == '__main__': 
    empdb = DataBase('employee.csv', 'Person') 
    print "retrieve(name='Ted Kingston'):", empdb.retrieve(name='Ted Kingston') 
    print "retrieve(age='27'):", empdb.retrieve(age='27') 
    print "retrieve(weight='150'):", empdb.retrieve(weight='150') 

回答

0

可變value在以下if .. for ..塊被覆蓋:

field, value = kwargs.items()[0] # <--- `value` defined 

... 

if field not in self.lookup_tables: 
    for index, record in enumerate(self.records): 
     value = getattr(record, field) # <--- `value` overwritten 
     self.lookup_tables[field][value].append(index) 

所以,value是指最後的記錄的值。您需要使用其他名稱來防止這種覆蓋。

if field not in self.lookup_tables: 
    for index, record in enumerate(self.records): 
     v = getattr(record, field) 
     self.lookup_tables[field][v].append(index) 
+0

謝謝你的幫助,它解決了它。 – salatwork