Es gibt nicht eine einzige Datenstruktur in Python gebaut, der alles tut, die Sie wollen , aber es ist ziemlich einfach, eine Kombination von den zu verwenden, die es hat, um Ihre Ziele zu erreichen, und zwar ziemlich effizient.
Zum Beispiel, sagen Sie Ihre Eingabe die folgenden Daten in einer kommagetrennten Wertdatei ist von der ersten Zeile genannt employees.csv
mit Feldnamen wie dargestellt definiert:
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
Der folgenden arbeiten Code, der zeigt, wie um diese Daten in einer Liste von Datensätzen zu lesen und zu speichern, und automatisch separate Nachschlagetabellen zum Auffinden von Datensätzen zu erzeugen, die den Werten der in jedem dieser Datensätze enthaltenen Felder zugeordnet sind.
Die Datensätze sind Instanzen einer Klasse, die von namedtuple
erstellt wurde. Dies ist sehr speichereffizient, da jedem ein __dict__
Attribut fehlt, das Klasseninstanzen normalerweise enthalten. Wenn Sie sie verwenden, können Sie auf die einzelnen Felder mit dem Namen mithilfe der Punktsyntax wie record.fieldname
zugreifen.
Die Look-up-Tabellen sind defaultdict(list)
Instanzen, die im Durchschnitt Wörterbuch ähnlichen O (1) Look-up-Zeiten liefern und erlauben auch mehr Werte mit jedem verbunden sein. Also ist der Nachschlageschlüssel der Wert des gesuchten Feldwertes, und die damit verbundenen Daten sind eine Liste der ganzzahligen Indizes der Person
Datensätze, die in der employees
Liste mit diesem Wert gespeichert sind - also werden sie alle relativ sein klein.
Beachten Sie, dass der Code für die Klasse vollständig datengesteuert ist, da er keine fest codierten Feldnamen enthält, die alle aus der ersten Zeile der csv-Dateneingabedatei stammen, wenn sie eingelesen wird verwendet werden, müssen alle tatsächlichen retrieve()
Methodenaufrufe natürlich gültige Feldnamen-Schlüsselwortargumente enthalten.
aktualisieren
Modified nicht eine Lookup-Tabelle für jeden eindeutigen Wert jedes Feld zu erzeugen, wenn die Datendatei zuerst gelesen wird. Jetzt erstellt die Methode retrieve()
sie nur bei Bedarf (und speichert/speichert das Ergebnis für die zukünftige Verwendung). Auch geändert, um in Python 2.7+ einschließlich 3.x zu arbeiten.
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.')
Ausgang:
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
Könnten Sie bitte die -1 rechtfertigen? Es ist eine echte Programmierfrage. –
Vielleicht hilft dir das - http://wiki.python.org/moin/TimeComplexity? – kgr
Warum nicht sql dafür verwenden? Scheint angemessener. Python unterstützt sqlite. –