Algorytm poszukiwania folderu

głosy
0

Nie jestem pewien, czy jest to zwykle rodzaj pytanie, które zostanie poproszony tutaj, czy będę miał żadnych odpowiedzi na ten jeden, ale szukam podejście pseudo-kod do generowania DB rekordy z linkami Struktura folderów zawierających wizerunek akta.

Mam zestaw folderów, strukturę 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
  ...  ... ...  

W istocie, to oznacza możliwych obrazów dla pojazdów, których autorem roku, poczynając od 1999 roku.

Marek i modeli (np Marka: Alfa Romeo Model: 145) są w różnych wersjach wykończenia lub. Każdy stan, lub wersję można znaleźć w wielu pojazdach, które będą wyglądać tak samo, ale mają powiedzieć różnice w rodzaju paliwa lub pojemności silnika.

Aby zapisać powielania, struktura folderów powyżej korzysta z domyślnego folderu ... I obrazy pojawiają się na domyślnej wersji z 2000 roku. Muszę produkować tabelę linki do każdej wersji - na podstawie tego, czy mają swoje nadrzędne obrazów, czy też skorzystać z wersji domyślnej ...

Tak na przykład, VERSION_1 nie ma plików graficznych, więc muszę dokonać linków do domyślnych obrazów, począwszy od roku 2000 aż do 2009 roku i kontynuowanej.

Wersja 2 z drugiej strony zaczyna się przy użyciu domyślnych obrazów w 2000 roku, ale potem wykorzystuje dwa nowe zestawy pierwszy na lata 2001-2002, a następnie 2003-2009. Lista linków są wymagane w związku z tym ...

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

(Domyślnie jest tak, że - posiadacz miejsce, a żadne powiązania są wymagane dla niego).

W tej chwili biegnę przez foldery, budowanie tablic, a następnie przycinanie tłuszczu na końcu. Zastanawiam się, czy istnieje skrót, używając jakiegoś podejścia do przetwarzania tekstu? Istnieje około 45000 foldery, z których większość jest pusta :-)

Utwórz 05/07/2009 o 21:43
źródło użytkownik
W innych językach...                            


1 odpowiedzi

głosy
1

Oto niektóre Python pseudokod, całkiem blisko do pliku wykonywalnego (wymaga odpowiedniego importu i def dla funkcji writerow że zrobi to samo pisanie - czy to do pliku pośredniego, DB, CSV, cokolwiek):

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

Jeden dwuznaczność w specyfikacji i przykładem jest to, czy jest to możliwe dla default_version zmienić zestaw plików w niektórych latach - tu, jestem przy założeniu, że nie nastąpi (tylko w wybranych wersjach zmienić w ten sposób, wersja domyślna zawsze niesie jeden zestaw plików).

Jeśli tak nie jest, to, co się dzieje w przypadku zmiany domyślnej wersji w latach (powiedzmy) 1999 i 2003 oraz zmiany version1 w 2001 i 2005 roku - jakie pliki powinny wersja 1 stosowanie do 03 i 04 nowymi, w wersji domyślnej lub tych, których określono w 01?

W najbardziej skomplikowanej wersji specyfikacji (gdzie zarówno default_version i specyficzny można zmienić, z ostatniej zmiany mającego pierwszeństwo, a jeśli zarówno specyficzne i domyślne zmiana w tym samym roku, a następnie konkretne mającego pierwszeństwo) trzeba uzyskać wszystkie „w przyszłym roku zmiana” sekwencja, dla każdej wersji, poprzez ostrożne „priorytetowej” łączenia sekwencji przemian lat za zwłokę i określonej wersji, zamiast tylko za pomocą years(kolejność zmian w konkretnej wersji), jak to zrobić tutaj - a każdy rok zmiana umieszczone w kolejności muszą być powiązane z odpowiednim zestawem plików oczywiście.

Więc jeśli dokładna specyfikacja może być wyrażona proszę, aż do przypadków narożnych, mogę pokazać jak wykonać potrzebne łączenie poprzez modyfikację tego Pseudokod - Wolałbym nie wykonywać pracę aż dokładne specyfikacje są wyjaśnione, ponieważ, jeśli specyfikacje są rzeczywiście prostsze, praca byłoby niepotrzebne! -)

Edit : jak nowy komentarz wyjaśnić, dokładne specyfikacje rzeczywiście jest najbardziej skomplikowana, więc musimy zrobić zrobić łączących odpowiednio. Więc pętli na końcu odpowiedź uproszczonym powyżej zmian:

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)

Kluczową zmianą jest merged = dict(...linia: w Pythonie, to znaczy, aby połączyły się nowy dict (dict jest ogólnym mapping, będzie zazwyczaj nazywa HashMap w innych językach), która jest sumą lub łączenia, z default_version, a years_dict, ale kiedy kluczem jest obecny w obu tych, wartość ze years_dictma pierwszeństwo - która spełnia warunek kluczowy dla roku, który jest obecny (czyli jest rok ze zmianą plików) w obu.

Po tym, że to całkiem proste: anydict.pop (somekey) zwraca wartość odpowiadającą klucza (a także usuwa go z anydict); min (anydict) zwraca co najmniej klucz słownika. Zwróć uwagę na „pusta” idiom w merged[max_year + 1] = None: ten mówi, że rok „jeden po max jednego” jest zawsze uważane za zmianę roku (z manekina wartości zastępczego z None), tak, że ostatni zestaw wierszy jest zawsze poprawnie napisane (z maksymalnym roku max_year + 1 - 1, to znaczy dokładnie max_year, jak to pożądane).

Algorytm ten nie jest maksymalnie wydajny, wystarczy najprostsza! Robimy min(merged)kółko, co czyni go O (N kwadratu) - myślę, że możemy sobie na to pozwolić, ponieważ każdy mergedpowinien mieć kilkadziesiąt przełączeń lat co najwyżej, ale purist by skrzywić. Możemy oczywiście przedstawić O Solution (N logN) - wystarczy posortować lat raz na zawsze i iść tą sekwencję, aby dostać kolejne wartości next_change. Tylko dla zasady ...:

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

Tutaj sorteddaje listę kluczy mergedposortowanych, a ja już włączony do forrachunku chodzić tę listę od początku do końca (i jeśli nic oświadczenia do wyjścia za pierwszym razem). Sentinel jest teraz umieścić w default_version (dlatego na zewnątrz pętli, na innym lekkim optymalizacji). To zabawne, aby zobaczyć, że ta wersja zoptymalizowana (głównie dlatego, że działa na nieco wyższym poziomie abstrakcji) okazuje się być mniejsze i prostsze niż poprzednie ;-).

Odpowiedział 05/07/2009 o 22:57
źródło użytkownik

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