Ordner Suchalgorithmus

stimmen
0

Nicht sicher, ob dies die übliche Art von Frage, die hier gefragt wird, oder ob ich irgendwelche Antworten auf diese bekommen werde, aber ich bin auf der Suche nach einem Pseudo-Code Ansatz zur Erzeugung von DB Verknüpfung Datensätze aus einem Ordnerstruktur mit Bild Dateien.

Ich habe eine Reihe von Ordnern, wie folllows strukturiert:

+-make_1/
  | +--model_1/
  |    +-default_version/
  |    |   +--1999
  |    |   +--2000
  |    |   |   +--image_01.jpg
  |    |   |   +--image_02.jpg
  |    |   |   +--image_03.jpg
  |    |   |   ...
  |    |   +--2001
  |    |   +--2002
  |    |   +--2003
  |    |   ...
  |    |   +--2009
  |    +--version_1/
  |    |   +--1999
  |    |   ...
  |    |   +--2009
  |    +--version_2/
  |    |   +--1999
  |    |   +--2000
  |    |   +--2001
  |    |   |   +--image_04.jpg
  |    |   |   +--image_05.jpg
  |    |   |   +--image_06.jpg
  |    |   |   ...
  |    |   +--2002
  |    |   +--2003
  |    |   |   +--image_07.jpg
  |    |   |   +--image_08.jpg
  |    |   |   +--image_09.jpg
  |    |   ...
  |    |   +--2009
  ...  ... ...  

Im Wesentlichen stellt es möglich, Bilder für Fahrzeuge, nach Jahren im Jahr 1999 beginnen.

Marken und Modelle (zB Marke: Alfa Romeo, Modell: 145) gibt es in verschiedenen Ordnungen oder Versionen. Jede trimmt oder Version kann in einer Anzahl von Fahrzeugen zu finden, die gleich aussehen, sondern zu sagen haben Unterschiede in dem Kraftstofftyp oder Hubraum.

So speichern Sie macht Vervielfältigung, die Ordnerstruktur über die Verwendung eines Standard-Ordner ... und Bilder erscheinen für die Standardversion ab dem Jahr 2000. Ich brauche die Links-Tabelle für jede Version zu produzieren - je nachdem, ob die eigenen übergeordnete Bilder haben, oder ob nutzen die Standard-Version ...

So hat zum Beispiel version_1 keine Bilddateien, also muß ich für die Standardbilder Links machen, im Jahr 2000 beginnen und bis 2009 fortgesetzt wird.

Version 2 auf der anderen Seite beginnt mit den Standardbildern im Jahr 2000, aber dann wird zwei neue Sätze zunächst für den Zeitraum 2001-2002, und dann 2003-2009. Die Liste der Links erforderlich sind daher ...

version    start     end   file_name
=======    =====   =====   =========
version_1   2000    2009   image_01.jpg
version_1   2000    2009   image_02.jpg
version_1   2000    2009   image_03.jpg
...
version_2   2000    2001   image_01.jpg
version_2   2000    2001   image_02.jpg
version_2   2000    2001   image_03.jpg
version_2   2001    2003   image_04.jpg
version_2   2001    2003   image_05.jpg
version_2   2001    2003   image_06.jpg
version_2   2003    2009   image_07.jpg
version_2   2003    2009   image_08.jpg
version_2   2003    2009   image_09.jpg
...

(Standardeinstellung ist nur, dass - ein Platzhalter und keine Links sind dafür erforderlich.)

Im Moment arbeite ich renne durch die Ordner, Gebäude Arrays und dann das Fett am Ende trimmen. Ich habe mich nur gefragt, ob es eine Abkürzung war, irgendeine Art von Textverarbeitungs Ansatz? Es gibt etwa 45.000 Ordner, von denen die meisten leer sind :-)

Veröffentlicht am 05/07/2009 um 21:43
quelle vom benutzer
In anderen Sprachen...                            


1 antworten

stimmen
1

Hier einige Python Pseudo-Code, ziemlich nah an ausführbare Datei (muss geeignete Importe und eine def für eine writerow Funktion, die die eigentliche Schreiben tun - sei es in eine Zwischendatei, DB, CSV, was auch immer):

# first, collect all the data in a dict of dicts of lists
# first key is version, second key is year (only for non-empty years)

tree = dict()
for root, dirs, files in os.walk('make_1/model_1'):
    head, tail = os.path.split(root)
    if dirs:
       # here, tail is a version
       tree[tail] = dict
    elif files:
       # here, tail is a year
       tree[os.path.basename(head)][tail] = files

# now specialcase default_version
default_version = tree.pop('default_version')
# determine range of years; rule is quite asymmetrical:
#   for min, only years with files in them count
min_year = min(d for d in default_version if default_version[d])
#   for max, all years count, even if empty
max_year = max(default_version)

for version, years in tree.iteritems():
    current_files = default_version[min_year]
    years.append(max_year + 1)
    y = min_year
    while years:
        next_change = min(years)
        if y < next_change:
            for f in current_files:
                writerow(version, y, next_change-1, f)
        y = next_change
        current_files = years.pop(y)

Eine Zweideutigkeit in der Spezifikation und Beispiel dafür ist, ob es möglich ist, für die default_version den Satz von Dateien in einigen Jahren zu ändern - hier, ich gehe davon aus, dass nicht den Fall (nur bestimmte Versionen ändern, dass die Art und Weise, die Standardversion trägt immer einen Satz von Dateien).

Ist dies nicht der Fall ist, was passiert, wenn die Standardversion Änderungen in Jahren (sagen wir) 1999 und 2003, und version1 Änderungen in den Jahren 2001 und 2005 -, welche Dateien sollten Version 1 Verwendung für 03 und 04, die neuen in der Standard-Version oder solche, es in 01 angegeben?

In der komplizierteste Version der Spezifikation (wobei beide default_version und ein spezifisches kann, mit der jüngsten Änderung ändert Vorrang nehmen, und wenn sowohl spezifische als auch Standard - Änderung im selben Jahr dann der spezifische Vorrang) muss man alle bekommen „nächste Änderung Jahr“ -Sequenz, für jede spezifische Version, durch sorgfältige „Priorität Verschmelzung“ der Sequenzen von Wechseljahre für Ausfall- und spezifische Version, statt nur mit years(der Folge von Änderungen in der spezifischen Version) , wie ich hier zu tun - und jede Veränderung Jahr in der Reihenfolge gebracht wird, muß mit dem entsprechenden Satz von Dateien natürlich in Verbindung gebracht werden.

Also, wenn die genaue Spezifikation können Sie bis in die Ecke Fälle ausgedrückt werden, kann ich zeigen, wie durch Änderung dieser Pseudo-Code die benötigte Verschmelzung zu tun - ich würde eher die Arbeit nicht tun, bis die genauen Spezifikationen geklärt werden, weil, wenn die Spezifikationen sind in der Tat einfacher, wäre die Arbeit nicht mehr benötigt! -)

Edit : als ein neuer Kommentar zu klären, die genauen Spezifikationen sind in der Tat die komplexeste, also müssen wir tun , tun die Zusammenführung angemessen. So die Schlaufe am Ende der simplen Antwort über Änderungen an:

for version, years_dict in tree.iteritems():
    # have years_dict override default_version when coincident
    merged = dict(default_version, **years_dict)
    current_files = merged.pop(min_year)
    merged[max_year + 1] = None
    y = min_year
    while merged:
        next_change = min(merged)
        for f in current_files:
            writerow(version, y, next_change-1, f)
        y = next_change
        current_files = merged.pop(y)

Der Schlüssel Änderung ist die merged = dict(...Zeile: in Python, bedeutet dies eine neue dict (a dict ist eine generische Abbildung, würde in der Regel eine hashmap in anderen Sprachen aufgerufen werden), damit verschmolzen , was die Summe oder fusioniert, von default_versionund years_dict, aber wenn ein Schlüssel in diesen beide vorhanden sind, von dem Wert years_dictVorrang hat - was die Grundvoraussetzung für ein Jahr entspricht , die vorhanden ist (dh ein Jahr mit einer Änderung der Dateien) in beide.

Danach ist es eine klare Sache: anydict.pop (somekey) auf den Schlüssel , den Wert zurückgibt entsprechenden (und entfernt es auch aus anydict); min (anydict) gibt die Minimal Schlüssel im Wörterbuch. Beachten Sie das „Sentinel“ Idiom an merged[max_year + 1] = None: Das sagt , dass das Jahr „ein nach dem max einem“ immer als ein Wechsel Jahr (mit einem Dummy - Platzhalter Wert von None) sein, so dass der letzte Satz von Zeilen immer richtig geschrieben (mit einem Maximum von Jahr max_year + 1 - 1, das genau ist max_year, wie gewünscht).

Dieser Algorithmus ist nicht maximal effizient, nur einfachste! Wir tun min(merged)immer und immer wieder , so dass es O (N zum Quadrat) - Ich denke , wir können das leisten , weil jeder mergedein paar Dutzend Wechseljahre höchstens haben sollte, aber ein Purist würde zusammenzucken. Wir können natürlich auch präsentieren einen O (N log N) Lösung - sortieren nur die Jahre ein für allemal und diese Sequenz zu Fuß für die aufeinander folgenden Werte zu erhalten next_change. Nur der Vollständigkeit halber ...:

default_version[max_year + 1] = None

for version, years_dict in tree.iteritems():
    merged = dict(default_version, **years_dict)
    for next_change in sorted(merged):
        if next_change > min_year:
            for f in merged[y]:
                writerow(version, y, next_change-1, f)
        y = next_change

Hier sortedgibt eine Liste mit den Tasten mergedin sortierter Reihenfolge, und ich habe mit der geschalteten forAussage , dass die Liste von Anfang an laufen bis zum Ende (und ein if - Anweisungen zur Ausgabe nichts das erste Mal durch). Der Wächter ist jetzt in default_version setzen (es ist also außerhalb der Schleife, für eine weitere leichte Optimierung). Es ist lustig zu sehen , dass diese optimierte Version stellt sich heraus , dass er kleiner und einfacher als die vorherigen ;-) ( im Wesentlichen , weil es auf einem etwas höheren Abstraktionsebene funktioniert).

Beantwortet am 05/07/2009 um 22:57
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more