2016-06-27 4 views
1

테이블 형식 데이터를 저장하고 여러 필드 값을 기반으로 레코드를 검색하려면 조회 테이블을 만들어야합니다.namedtuple 레코드 구조에서 데이터 검색 실패

나는 거의 필요한 모든 것을 수행하는 예제 인 post # 15418386을 발견했지만 전달 된 인수에 관계없이 항상 동일한 레코드를 반환합니다. 이 글의 맨 아래에 코드가 나열되어 있습니다. 링크가 작동하지 않습니다.

필자는 IDE에서 디버거를 사용하여 파일이 올바르게 읽혀지고 데이터 테이블이 올바르게 채워지는지 확인했습니다 (Im은 PyCharm을 사용함). 코드에 포함

테스트 데이터는 다음과 같습니다

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