Không có một cấu trúc dữ liệu duy nhất được xây dựng vào Python mà làm mọi thứ bạn muốn , nhưng nó khá dễ dàng để sử dụng một sự kết hợp của những người nó phải đạt được mục tiêu của bạn và làm như vậy khá hiệu quả.
Ví dụ, nói đầu vào của bạn là dữ liệu sau đây trong một tập tin bằng dấu phẩy giá trị gọi là employees.csv
với tên trường được định nghĩa như thể hiện bởi những dòng đầu tiên:
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
Các mã sau đây được làm việc minh họa cách để đọc và lưu trữ dữ liệu này vào danh sách các bản ghi và tự động tạo các bảng tìm kiếm riêng biệt để tìm các bản ghi liên kết với các giá trị chứa trong các trường của mỗi bản ghi này.
Bản ghi là trường hợp của một lớp được tạo bởi namedtuple
là bộ nhớ rất hiệu quả vì mỗi bản ghi thiếu thuộc tính __dict__
mà các cá thể lớp thường chứa. Sử dụng chúng sẽ làm cho nó có thể truy cập vào các lĩnh vực của từng tên bằng cách sử dụng cú pháp dấu chấm, như record.fieldname
.
Các bảng nhìn lên là defaultdict(list)
trường hợp, trong đó cung cấp từ điển giống như O (1) nhìn lên lần trên trung bình, và cũng cho phép nhiều giá trị có liên quan đến mỗi một. Vì vậy, khóa tìm kiếm là giá trị của giá trị trường được tìm kiếm và dữ liệu được liên kết với nó sẽ là danh sách các chỉ số nguyên của các bản ghi Person
được lưu trữ trong danh sách employees
với giá trị đó - vì vậy tất cả chúng sẽ tương đối nhỏ bé.
Lưu ý rằng mã cho lớp hoàn toàn hướng dữ liệu ở chỗ nó không chứa bất kỳ tên trường được mã hóa nào thay vào đó được lấy từ hàng đầu tiên của tệp nhập dữ liệu csv khi được đọc. được sử dụng, mọi cuộc gọi phương thức thực tế retrieve()
phải, tất nhiên, chứa các đối số từ khóa tên trường hợp lệ.
Cập nhật
Modified để không tạo ra một bảng tra cứu cho mỗi giá trị duy nhất của tất cả các lĩnh vực khi các tập tin dữ liệu là đầu đọc. Bây giờ phương thức retrieve()
chỉ tạo chúng khi cần (và lưu/lưu trữ kết quả để sử dụng sau này). Cũng được sửa đổi để làm việc trong Python 2.7+ bao gồm 3.x.
from collections import defaultdict, namedtuple
import csv
class DataBase(object):
def __init__(self, csv_filename, recordname):
# Read data from csv format file into a list of namedtuples.
with open(csv_filename, 'r') as inputfile:
csv_reader = csv.reader(inputfile, delimiter=',')
self.fields = next(csv_reader) # 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 = list(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('employees.csv', 'Person')
print("retrieve(name='Ted Kingston'): {}".format(empdb.retrieve(name='Ted Kingston')))
print("retrieve(age='27'): {}".format(empdb.retrieve(age='27')))
print("retrieve(weight='150'):".format(empdb.retrieve(weight='150')))
try:
print("retrieve(hight='5ft 6in'):".format(empdb.retrieve(hight='5ft 6in')))
except ValueError as e:
print("ValueError('{}') raised as expected".format(e))
else:
raise type('NoExceptionError', (Exception,), {})(
'No exception raised from "retrieve(hight=\'5ft\')" call.')
Output:
retrieve(name='Ted Kingston'): [Person(name='Ted Kingston', age='28', weight='163', height='5ft 10in')]
retrieve(age='27'): [Person(name='Mary Manson', age='27', weight='140', height='5ft 6in'),
Person(name='Sue Sommers', age='27', weight='132', height='5ft 8in')]
retrieve(weight='150'): None
retrieve(hight='5ft 6in'): ValueError('keyword arg "hight" is an invalid fieldname')
raised as expected
Ông có thể biện minh cho việc -1? Đó là một câu hỏi lập trình chính hãng. –
Có thể điều này sẽ giúp bạn - http://wiki.python.org/moin/TimeComplexity? – kgr
Tại sao không sử dụng sql cho điều này? Có vẻ thích hợp hơn. Python đã xây dựng hỗ trợ cho sqlite. –