Dossier algorithme de recherche

voix
0

Je ne sais pas si cela est le genre de question habituelle qui obtient demandé ici, ou si je vais obtenir des réponses à celui-ci, mais je suis à la recherche d'une approche pseudo-code pour générer DB reliant les enregistrements à partir d'une structure de dossiers contenant l'image des dossiers.

J'ai un ensemble de dossiers, structurés comme folllows:

+-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
  ...  ... ...  

En substance, il représente les images possibles pour les véhicules, par année à compter de 1999.

Marques et modèles (par exemple Marque: Alfa Romeo, Modèle: 145) viennent en différentes versions ou versions. Chaque garniture, ou une version se trouvent dans un certain nombre de véhicules qui ont le même aspect, mais ont dit des différences de type de carburant ou de la capacité du moteur.

Pour enregistrer la duplication, la structure des dossiers ci-dessus utilise un dossier par défaut ... Et les images apparaissent pour la version par défaut à partir de 2000. Je dois produire la table de liens pour chaque version - selon que l'ont leurs propres images prépondérants, ou si faire usage de la version par défaut ...

Ainsi, par exemple, VERSION_1 n'a pas de fichiers d'image, donc je besoin de faire des liens pour les images par défaut, à partir de 2000 et continue jusqu'en 2009.

La version 2 d'autre part commence à l'aide des images par défaut en 2000, mais utilise ensuite deux nouveaux ensembles d'abord pour 2001-2002, puis 2003-2009. La liste des liens nécessaires sont donc ...

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
...

(Par défaut est juste que - un porte-lieu, et aucun lien sont nécessaires pour cela.)

En ce moment je suis en cours d'exécution à travers les dossiers, les tableaux de construction, puis Dégraisser à la fin. Je me demandais s'il y avait un raccourci, en utilisant une sorte d'approche de traitement de texte? Il y a environ 45 000 dossiers, dont la plupart sont vides :-)

Créé 05/07/2009 à 21:43
source utilisateur
Dans d'autres langues...                            


1 réponses

voix
1

Voici quelques Python pseudocode, assez proche de l'exécutable (besoins des importations appropriés et une définition pour une fonction writerow qui fera l'écriture réelle - que ce soit dans un fichier intermédiaire, DB, CSV, peu importe):

# 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)

Une ambiguïté dans la spécification et l'exemple est de savoir s'il est possible pour le default_version de changer l'ensemble des fichiers dans quelques années - ici, je suppose que cela ne se produit pas (seulement versions spécifiques changent cette façon, la version par défaut porte toujours un jeu des fichiers).

Si ce n'est pas le cas, ce qui se passe si les changements de version par défaut au cours des années (disons) 1999 et 2003, et les changements de Version1 en 2001 et 2005 - quels fichiers devraient version 1 utilisation pour 03 et 04, les nouvelles dans la version par défaut ou ceux qu'il a précisé dans 01?

Dans la version la plus compliquée de la spécification (où les deux default_version et un spécifique peut changer, avec la dernière modification primant, et si les deux changements spécifiques et par défaut de la même année alors la priorité spécifique de prise) , on a besoin d'obtenir toutes les séquence « l'année prochaine de changement », pour chaque version spécifique, par attention « fusion prioritaire » des séquences d'années de changement pour défaut et version spécifique, au lieu d'utiliser years(la séquence des changements dans la version spécifique) comme je le fais ici - et chaque année de changement placé dans la séquence doit être associée à l'ensemble approprié de fichiers bien sûr.

Donc, si la spécification exacte peut être exprimée s'il vous plaît, jusqu'aux cas de coin, je peux montrer comment faire la fusion nécessaire en modifiant ce pseudo - Je préfère ne pas faire le travail jusqu'à ce que les spécifications exactes sont clarifiées, parce que, si le les spécifications sont en effet plus simple, le travail serait inutile -)

Modifier : comme un nouveau commentaire précise, les spécifications exactes est en effet le plus complexe, nous avons donc faire faire la fusion appropriée. Ainsi , la boucle à la fin de la réponse simpliste au- dessus des modifications à:

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)

Le principal changement est la merged = dict(...ligne: en Python, cela signifie de faire fusionner une nouvelle dict (un dict est une application générique, serait généralement appelé hashmap dans d' autres langues) , qui est la somme, ou une fusion, de default_versionet years_dict, mais lorsqu'un clé est présente dans les deux ceux -ci , la valeur de l' years_dictemporte - qui répond à la condition sine qua non pour une année qui est présent (c. -à- est une année avec un changement de fichiers) dans les deux.

Après cela , il est un long fleuve tranquille: anydict.pop (somekey) renvoie la valeur correspondant à la clé (et supprime également de anydict); min (anydict) renvoie la clé minimale dans le dictionnaire. Notez l'expression « sentinelle » à merged[max_year + 1] = None: ce dit que l'année « l' un après l'un max » est toujours considérée comme un changement année (avec une valeur de paramètre fictif fictif de None), de sorte que le dernier ensemble de lignes est toujours écrit correctement (avec un an maximum max_year + 1 - 1, qui est, exactement max_year, comme on le souhaite).

Cet algorithme n'est pas une efficacité maximale, tout simple! Nous faisons min(merged)encore et, ce qui en fait O (N carré) - Je pense que nous pouvons nous permettre que parce que chacun mergeddevrait avoir quelques dizaines de changements années au plus, mais les puristes grimacer. Nous pouvons bien sûr présenter un O (N logN) solution - il suffit de trier les années une fois pour toutes et marcher cette séquence pour obtenir les valeurs successives pour next_change. Juste pour être complet ...:

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

Voici sorteddonne une liste avec les touches de mergeddans l' ordre de tri, et je l' ai passé à la fordéclaration de marcher cette liste du début à la fin (et une instruction if pour rien de sortie la première fois par le biais). La sentinelle est maintenant mis en default_version (il est donc en dehors de la boucle, pour une autre légère optimisation). Il est amusant de voir que cette version optimisée (essentiellement parce qu'il fonctionne à un niveau d'abstraction légèrement plus élevé) se révèle être plus petit et plus simple que les précédents ;-).

Créé 05/07/2009 à 22:57
source utilisateur

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