Was ist der effizienteste Weg, um diese Daten zu speichern?


9

Ich bin dafür verantwortlich, einen alten VB-Code neu zu schreiben. Ich verstehe, wie es funktioniert, aber ich habe das Gefühl, dass es einen weitaus effizienteren Weg gibt, das zu tun, was sie getan haben. Ich kann einfach nicht herausfinden, was es ist. Hier ist ein erfundenes Beispiel, das in Bezug auf die Datenanforderungen wirklich dem entspricht, was ich tun muss.

Der Benutzer muss den Hersteller, die Marke, das Modell und die Farbe seines Autos in einer grafischen Benutzeroberfläche auswählen. Ich habe eine große Textdatei, die ungefähr so ​​aussieht:

Ford Truck F150 red
Ford Truck F150 blue
Ford Truck F150 black
Ford Truck F150 silver
Ford Truck F250 red
Ford Truck F250 green
Ford Sedan Taurus red
Ford Sedan Taurus green
Ford Sedan Taurus white
Ford...
...

Subaru SUV Forester blue
Subaru SUV Forester red
Subaru SUV Outback Black
Subaru SUV Outback Green
Subaru SUV Outback Blue
Subaru SUV Outback Red
Subaru...
...

etc.

Wenn die erste Auswahl Subaru ist, sollte das zweite Feld (Marke) keine Option zur Auswahl von LKW haben, da keiner der Subarus LKWs sind. Wenn sie Ford, Sedan und Taurus auswählen, sollte das letzte Feld (Farbe) keine Option zur Auswahl von Blau enthalten. Oder schwarz. Oder etwas anderes als rot, grün oder weiß.

Die Leute, die den Code vor mir geschrieben haben, haben sich das ausgedacht (im Python-y-Pseudocode):

def getValidOptions():
    items = []
    for i from 0 to numRows:
        options = getLine().split()
        if selectingManufacturer:
            if options[0] not in items:
                items.append(options[0])
        else if selectingMake:
            if selectedManufacturer == options[0] and options[1] not in items:
               items.append(options[1])
        else if selectingModel:
            if selectedManufacturer == options[0] and selectedMake == options[1] and options[2] not in items:
                items.append(options[2])
        else if selectingColor:
            if selectedManufacturer == options[0] and selectedMake == options[1] and selectedModel == options[2] and options[3] not in items:
                items.append(options[3])
    return items

Ich finde das einfach abscheulich, sowohl auf Algorithmus- als auch auf Syntaxebene. Zum einen analysiert es die gesamte Datei, wenn es nur ein paar Zeilen durchlesen muss, wenn es richtig gemacht wird. Um dies noch ineffizienter zu machen, haben meine realen Daten 6 Optionen zur Auswahl und nicht nur 4. Dies speichert auch mehr Daten als nötig, angesichts des Umfangs der Datenverdoppelung.

Ich suche entweder nach einer anderen Methode zum Speichern der Daten in der Datei oder nach einer anderen Methode zum Parsen, um die getValidOptionsFunktion sowohl hübscher als auch effizienter zu gestalten. Gibt es Möglichkeiten, wie ich das tun könnte?


2
Warum nicht eine Datenbank verwenden?
Tulains Córdova

Antworten:


6

Alle anderen Antworten, die ich lese, scheinen zwei sehr grundlegende Regeln der Softwareentwicklung zu ignorieren:

  • Klären Sie zuerst die Anforderungen (insbesondere die Leistungs- und Speicheranforderungen).

  • Halte es einfach, dumm (siehe KISS )

Sie haben "Die Textdatei ist groß" geschrieben, aber nicht zu groß geschrieben. Ich gehe also davon aus, dass an der Größe nichts auszusetzen ist, außer Ihrem Bauchgefühl. Wenn das Laden der Datei nicht zu lange dauert und Ihre IT-Abteilung oder eine andere Person sich nicht über den verschwendeten Speicherplatz beschwert und sich niemand über Probleme bei der Pflege der Datei beschwert, lassen Sie das Dateiformat unverändert. Unterschätzen Sie das nicht Wert der Einfachheit.

Sie beschweren sich auch über die Effizienz des Algorithmus, der eigentlich nicht so effizient ist, wie er sein könnte, aber einen sehr großen Vorteil hat: Er ist hirntot einfach und funktioniert. Wenden Sie keine vorzeitige Optimierung an, solange dies effizient genug ist.

Nehmen wir also an, das Programm funktioniert schnell genug. Zunächst sollten Sie sich fragen, wie Sie den Code in Bezug auf Einfachheit und DRY-Prinzip verbessern können. Und das ist in der Tat ein Punkt, der verbessert werden sollte, da der aktuelle Code nicht trocken ist. In Ihrem Beispiel wird viermal fast derselbe Codeblock getestet, wenn die Optionen auf den "höheren Ebenen" mit der aktuellen Zeile übereinstimmen. Dies führt zu viermal der gleichen Art von "Anhängen" -Aufruf (in Ihrem realen Code tritt die Wiederholung auf mindestens sechsmal, wie du geschrieben hast). Sie können dies leicht vermeiden, indem Sie eine numerische Auswahlstufe einführen oder die bereits ausgewählten Optionen in einer geordneten Liste übergeben. Wenn Sie Ihren Pseudocode verwenden, führt dies zu etwas in der Art von

# selectedOptions is a list, containing either nothing, or "selectedManufacturer"
# or [selectedManufacturer, selectedMake], ..., and so on
def getValidOptions(selectedOptions):
    items = []
    level = selectedOptions.size()
    for i from 0 to numRows:
        options = getLine().split()
        if selectedOptions == options[0:level-1] and options[level] not in item:
            items.append(options[level])
    return items

Dies ist also im Wesentlichen derselbe Algorithmus ohne wiederholten Code mehr.

Da es offensichtlich getValidOptionsist, dass mehr als einmal aufgerufen werden muss (mindestens einmal pro Ebene), empfehle ich, nur eine Optimierung anzuwenden (falls dies nicht bereits der Fall ist): Stellen Sie sicher, dass die getLineFunktion ihre Daten aus dem Hauptspeicher abruft und nicht Lesen Sie die Datei immer wieder von der Festplatte.


Sie möchten "level = selectedOptions.size ()" vor die numRows-Schleife verschieben.
AI Breveleri

6

Nun, die Daten, die Sie haben, haben eine baumartige Struktur, wobei Sie für jeden Hersteller einen Baum von Modellen haben und für jedes Modell eine Farbe (und so weiter).

Sie können den Prozess dieser Daten also in zwei Schritten trennen:

  1. Nach jeder Aktualisierung der Textdatei müssen Sie diese Datei verarbeiten und in eine Baumstruktur konvertieren.
  2. Beim Laden der Anwendung laden Sie nur die Baumstruktur.

Die Baumstruktur kann mit einem sogenannten Hash , einem assoziativen Array oder einem Wörterbuch in Sprachen wie Java, PHP, Javascript oder Python implementiert werden. Mit dieser Struktur haben Sie:

  • Die ersten Schlüssel sind die Hersteller.
  • Ihre Werte sind nur weitere Hashes oder Wörterbücher, in denen jeder Schlüssel das Modell ist.
  • Ihre Werte sind die Farben. Oder eine andere Struktur, die in ihren Schlüsseln die dritte Ebene und als Wert die vierte Ebene behält.
  • Und so weiter...

Abhängig von Ihrer Programmiersprache kann dies schneller oder langsamer implementiert werden. Beispielsweise:

  • C # : Sie können eine Baumstruktur 1 implementieren und sie dann als serialisierbar markieren.
  • VB.Net : Sie können die Baumstruktur in einer Anwendung generieren und in einer Datei serialisieren.
    • Dafür Runtime.Serialization.Formatters.Binary.BinaryFormatterkönnte so etwas nützlich sein, aber ich bin kein Experte für die Serialisierung mit VB.Net.
  • Javascript : Sie können die Baumstruktur in einer JSON-Datei generieren, die bei jedem Laden der App geladen werden muss.
  • PHP : Sie können eine serialisierte Version der Baumdatenstruktur generieren oder auch einen JSON laden.
  • Java : Sie können diese Datenstruktur serialisieren und eine erstellen Class, die die Schnittstelle implementiert java.io.Serializable.

Referenzen :

1: https://dvanderboom.wordpress.com/2008/03/15/treet-implementing-a-non-binary-tree-in-c/
- Eine vollständige Erklärung zum Implementieren eines Baums in C #.
- Suchen Sie nach einem Kommentar, in dem jemand nach der Serialisierung dieses Objekts fragt , und nach der Antwort auf diesen Kommentar.


1
Ja, ich hatte über die Verwendung eines Baums nachgedacht, aber ich weiß nicht, ob dies die beste Idee ist, da es in C # keine eingebaute Baumstruktur (die ich kenne) gibt und das Projekt ziemlich klein ist, daher weiß ich nicht, ob Es lohnt sich, sehr viel Zeit mit der Arbeit an einer tree with an arbitrary number of nodesImplementierung zu verbringen .
James

Bis jetzt bin ich kein Experte für C #, aber zumindest in anderen Sprachen wie Java und PHP können Sie eine Art Wörterbuch haben, wobei jeder Schlüssel ein anderes Wörterbuch als Wert haben kann.
Nicolás

Ich habe meine Antwort aktualisiert. Sehen Sie, was Sie über die Hash- oder Wörterbuchalternative denken. Ich habe auch eine Referenz mit einem interessanten Artikel hinzugefügt.
Nicolás

3

Eine einfache Möglichkeit, die Daten zu speichern, besteht darin, sie einfach in eine SQLite-Datenbank zu speichern. SQLite eignet sich im Gegensatz zu den meisten SQL-Datenbanken gut zur Verwendung als Anwendungsdateiformat. Dieser Ansatz hat mehrere Vorteile:

  1. Sie müssen keinen Serializer oder Deserializer codieren.
  2. Die Datei kann von zahlreichen vorhandenen Programmen bearbeitet und abgefragt werden.
  3. Die bedingte Unordnung, die Sie in der Frage erwähnen, wird vermieden. Generieren Sie eine einfache where-Klausel für jede Spalte (z select distinct model where manufacturer='ford' and color = 'red'. B. ), um Dropdowns zu begrenzen .

Dadurch müssen Sie zwar SQL lernen, müssen jedoch kein benutzerdefiniertes Dateiformat erlernen.


1

Ich gehe davon aus, dass Sie zufällig auf Zeilen in der Datei zugreifen und die Datei somit als Array von Datensätzen behandeln können. Wenn Sie nicht zufällig auf die Zeilen zugreifen können, ist der Algorithmus, den Sie haben, der beste, den Sie tun können.

Speichern Sie die Daten für einen schnellsten Zugriff in 6 Dateien, wobei jede Datei ein Index für die nächste ist.

Es gibt viele Möglichkeiten, Flatfile-Indizes zu erstellen. Normalerweise verwende ich einen tiefgestellten Bereich. Verwenden Sie bei jeder Auswahl den Bereich, um das Lesen der nächsten Datei einzuschränken.

So würde ich die Indizes für die von Ihnen angegebenen Beispieldaten erstellen.

Natürlich muss die Datei sortiert werden. Ich habe die Zeilen zur Veranschaulichung nummeriert; Die Zeilennummern sollten nicht in der Datei erscheinen.

--| file3.dat |--
 0 Ford Truck F150 red
 1 Ford Truck F150 blue
 2 Ford Truck F150 black
 3 Ford Truck F150 silver
 4 Ford Truck F250 red
 5 Ford Truck F250 green
 6 Ford Sedan Taurus red
 7 Ford Sedan Taurus green
 8 Ford Sedan Taurus white
 9 Subaru SUV Forester blue
10 Subaru SUV Forester red
11 Subaru SUV Outback Black
12 Subaru SUV Outback Green
13 Subaru SUV Outback Blue
14 Subaru SUV Outback Red

Um den ersten Index zu erstellen, erstellen Sie einen Datensatz für jede eindeutige Kombination der ersten drei Felder in der Datei. Speichern Sie in jedem Datensatz die erste und letzte Zeilennummer, in der diese Kombination angezeigt wird.

--| file2.dat |--
 0 Ford Truck F150       0   3
 1 Ford Truck F250       4   5
 2 Ford Sedan Taurus     6   8
 3 Subaru SUV Forester   9  10
 4 Subaru SUV Outback   11  14

Der zweite Index wird ähnlich aufgebaut, wobei die ersten beiden Felder des ersten Index verwendet werden.

--| file1.dat |--
 0 Ford Truck        0   1
 1 Ford Sedan        2   2
 2 Subaru SUV        3   4

Und die dritte, in diesem Fall die oberste Ebene, der Index.

--| file0.dat |--
 0 Ford          0   1
 1 Subaru        2   2

Ich glaube, ich erkläre das Konzept übermäßig, aber im Allgemeinen erstellen Sie einen Index, indem Sie das letzte Feld löschen und doppelte Datensätze entfernen.

Sie können den Dateispeicherbedarf weiter reduzieren, indem Sie einige redundante Daten entfernen.

Beispielsweise ist der "erste" Index in jedem Indexdatensatz immer eins mehr als der "letzte" Index des vorherigen Datensatzes oder Null, wenn kein vorheriger Datensatz vorhanden ist. Sie müssen also nicht die "ersten" Indizes speichern. Ich lasse sie unten zur Veranschaulichung an Ort und Stelle.

Da Sie nur das letzte Feld in jedem Datensatz verwenden, um die Auswahlliste zu füllen, müssen Sie die anderen Felder nicht speichern.

Die minimale Wiedergabe der Indexkaskade sieht folgendermaßen aus, wobei das Häkchen 'eine Zahl anzeigt, die nicht tatsächlich in der Datei gespeichert ist.

--| file0.dat |--
 0' Ford         0'   1
 1' Subaru       2'   2

--| file1.dat |--
 0' Truck        0'   1
 1' Sedan        2'   2
 2' SUV          3'   4

--| file2.dat |--
 0' F150         0'   3
 1' F250         4'   5
 2' Taurus       6'   8
 3' Forester     9'  10
 4' Outback     11'  14

--| file3.dat |--
 0' red
 1' blue
 2' black
 3' silver
 4' red
 5' green
 6' red
 7' green
 8' white
 9' blue
10' red
11' Black
12' Green
13' Blue
14' Red

Wenn Sie eine Auswahlliste aus einem Index füllen, verwenden Sie die Indizes "first" und "last" aus der Auswahl des Benutzers im vorherigen Index, um die gelesenen Zeilen zu begrenzen.

Beispiel:

Sie füllen die erste Auswahlliste aus allen file0.dat. (Ford, Subaru)

Der Benutzer wählt "Ford". Die entsprechenden Indizes sind 0 und 1.

Sie füllen die zweite Auswahlliste aus den Zeilen 0 bis 1 von file1.dat. (LKW, Limousine)

Der Benutzer wählt "Limousine". Die entsprechenden Indizes sind 2 und 2.

Wie Sie sehen können, müssen Sie zum Zeitpunkt der Auswahl durch den Benutzer, z. B. "Ford", "Limousine", "Taurus", nur die Zeilen 6 bis 8 lesen file3.dat, um die vierte Auswahlliste zu füllen.

Ich entschuldige mich für die ziemlich lange Beschreibung, aber es ist sehr spät hier und ich habe keine Zeit, eine kurze zu schreiben.

HINZUGEFÜGT: Bei weiterer Überlegung können die Dateien zu einer verkettet werden.

--| file.dat |--
 0' -            1'   2
 1' Ford         3'   4
 2' Subaru       5'   5
 3' Truck        6'   7
 4' Sedan        8'   8
 5' SUV          9'  10
 6' F150        11'  14
 7' F250        15'  16
 8' Taurus      17'  19
 9' Forester    20'  21
10' Outback     22'  25
11' red          -'   -
12' blue         -'   -
13' black        -'   -
14' silver       -'   -
15' red          -'   -
16' green        -'   -
17' red          -'   -
18' green        -'   -
19' white        -'   -
20' blue         -'   -
21' red          -'   -
22' Black        -'   -
23' Green        -'   -
24' Blue         -'   -
25' Red          -'   -

Dies wird genau wie die Version mit mehreren Dateien verwendet, außer dass Sie die erste Dummy-Zeile benötigen, um den ersten Indexbereich zu enthalten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.