Алгоритм поиска папок

голоса
0

Не уверен, что если это обычный вид вопроса, который спрашивает здесь, или если я получу какие-либо ответы на этот, но я ищу псевдо-коду подход к генерации БД, связывающие записи из структуры папок, содержащих изображений файлы.

У меня есть набор папок, структурированных в 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
  ...  ... ...  

По сути, она представляет собой возможные изображения для транспортных средств, в разбивке по годам, начиная с 1999 года.

Делает и модели (например, Марка: Alfa Romeo, модель: 145) поставляются в различных подстройку или версий. Каждый подрезать, или вариант можно найти в ряде транспортных средств, которые будут выглядеть одинаково, но имеют сказать различия в типе топлива или мощности двигателя.

Для сохранения дублирования, структура папок выше использует папку по умолчанию ... И изображения появляются в версии по умолчанию с 2000 года. Мне нужно, чтобы получить таблицу ссылок для каждой версии - в зависимости от того есть свои верховные изображения, или делают использование версии по умолчанию ...

Так, например, VERSION_1 не имеет графических файлов, так что мне нужно сделать ссылки на образам по умолчанию, начиная с 2000 года и продолжается до 2009 года.

Версия 2 с другой стороны начинается использование изображений по умолчанию в 2000 году, но затем использует два новых набора первых на 2001-2002 годы, а затем 2003-2009. Перечень ссылок, необходимых поэтому ...

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

(По умолчанию только что - держатель места, и никаких ссылок не требуется для этого.)

На данный момент я бег по папкам, создание массивов, а затем обрезки жира в конце. Мне было просто интересно, если там был короткий путь, используя какой-то текст обработки подход? Есть около 45 000 папок, большинство из которых являются пустыми :-)

Задан 05/07/2009 в 21:43
источник пользователем
На других языках...                            


1 ответов

голоса
1

Вот некоторые Python псевдокод, довольно близко к исполняемому файлу (необходим подходящий импорт и размораживание для функции writerow, что будет делать фактическое написание - будь то в промежуточный файл, DB, CSV, что угодно):

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

Одна неясность в спецификации и примером является ли это возможно для default_version изменить набор файлов в несколько лет - здесь, я предполагаю, что не бывает (только определенные версии изменить таким образом, версия по умолчанию всегда несет один набор файлов).

Если это не так, что произойдет, если версия по умолчанию меняется внутриигровые лет (скажем) 1999 и 2003, а также изменения Version1 в 2001 и 2005 годах - какие файлы должны версии 1 использовать для 03 и 04, на новые в версии по умолчанию , или те, что указаны в 01?

В самой сложной версии спецификации (где оба default_version и специфический можно изменить, с самыми последними изменениями , имеющего приоритет, и если оба специфичны и по умолчанию изменения в том же году , то конкретное принятие старшинства) один должен получить все «Следующее изменение год» последовательность, для каждой конкретной версии, путем тщательного «приоритетного объединения» последовательностей лет изменения по умолчанию и конкретной версии, вместо того , чтобы просто используя years(последовательность изменений в конкретной версии) , как я здесь - и каждый год изменения размещен в последовательности должен быть связан с соответствующим набором файлов, конечно.

Таким образом, если точная спецификация может быть выражена просьба, вплоть до случаев угловых, я могу показать, как сделать необходимое слияние путем изменения этого псевдокода - Я предпочел бы не делать свою работу, пока точные данные не будут прояснены, потому что, если спецификации действительно проще, работа будет ненужной! -)

Edit : как новый комментарий выяснены точные данные действительно самый сложный, поэтому мы должны сделать сделать слияние надлежащим образом . Таким образом , петли в конце упрощенным ответа выше изменений:

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)

Ключевое изменение является merged = dict(...строкой: в Python, это означает , чтобы сделать слит новый Dict (а ДИКТ является родовым отображением, будет обычно называется HashMap на других языках) , который представляет собой сумму, или объединить, из default_versionи years_dict, но когда ключ присутствует в обеих из них, значение из years_dictимеет преимущество - что соответствует основному условию в течение года , который присутствует (то есть, это год с изменением файлов) в обеих.

После того, что это так гладко: anydict.pop (somekey) возвращает значение , соответствующее ключу (а также удаляет его из anydict); мин (anydict) возвращает минимальный ключ в словаре. Обратите внимание на «дозорные» идиомы на merged[max_year + 1] = None: это говорит о том, что год «один после максимального одного» всегда считается изменением курсом (с фиктивным значением заполнителя из None), так что последний набор строк всегда пишутся правильно (максимальный год max_year + 1 - 1, то есть, именно max_year, по желанию).

Этот алгоритм не является максимально эффективным, только простейшим! Мы делаем min(merged)снова и снова, что делаю его O (N в квадрате) - я думаю , что мы можем себе это позволить , потому что каждый mergedдолжен иметь несколько десятков переключающих лет в лучшем случае , но пурист бы вздрогнуть. Конечно , мы можем представить O решения (N LogN) - просто сортировать года раз и навсегда и пройти эту последовательность , чтобы получить последовательные значения next_change. Только для полноты ...:

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

Здесь sortedприведен список с ключами mergedв отсортированном порядке, и я переключился на forзаявление , чтобы идти , что список от начала до конца (и если заявления на выход ничего не в первый раз через). Сторожевой сейчас ставятся в default_version (так что вне цикла, для другой небольшой оптимизации). Забавно видеть , что это оптимизированная версия ( в основном потому , что она работает на более высоком уровне абстракции) оказывается меньше и проще , чем предыдущие ;-).

Ответил 05/07/2009 в 22:57
источник пользователем

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