Проверка или установка записей во вложенном dict из списка ключей переменной длины

#python #dictionary

#python #словарь

Вопрос:

У меня есть вложенный dict, который соответствует дереву каталогов, подобному этому:

 a:
  b:
    c: 1
    d: 1
  e:
    f:
      g: 1
      h: 1
...
 

в этом случае все ключи, которые получают число в качестве значения (c, d, g, h), являются файлами, все остальные записи являются папками. Теперь, учитывая путь типа «a / e / f / g», я хочу сделать следующее:

  • проверьте, существует ли my_dict[a], в противном случае создайте его
  • проверьте, существует ли my_dict[a][e], в противном случае создайте его
  • проверьте, существует ли my_dict[a][e][f], в противном случае создайте его
  • проверьте, существует ли my_dict[a][e][f][g], в противном случае создайте его и присвоите ему значение по умолчанию

Длина пути для разных файлов не является постоянной, поэтому я не могу выполнить простой chained .get() . Также я должен добавлять записи файл за файлом.

Я считаю, что я думаю слишком сложно. Есть ли какой-нибудь элегантный способ сделать это?

Редактировать: Пример:

У меня есть вложенный dict сверху и файл с путем «a / b / i / j» и значением по умолчанию = 1. Затем dict должен быть обновлен следующим образом:

 a:
  b:
    c: 1
    d: 1
    i:
      j: 1
  e:
    f:
      g: 1
      h: 1
...
 

Ответ №1:

 my_dict = {}
path = "a/e/f/g"
wd = my_dict  # Set working dictionary to my_dict
path_split = path.split('/')
for char in path_split[:-1]:  # Loop through all but the final char in the path
    if char not in wd or not isinstance(wd[char], dict):
        wd[char] = {}
    wd = wd[char]  # Set new working dictionary
if path_split[-1] not in wd:  # Check if final char is in the wd, if not set it to 1
    wd[path_split[-1]] = 1
 

Вам нужно проверить, что ключ существует в рабочем словаре и что соответствующее значение является словарем, затем установить рабочий словарь после каждой проверки.

Комментарии:

1. спасибо за предложение. я согласен, что это сработало бы, если бы в моем dict была только одна запись на каждом уровне. однако на каждом уровне может быть несколько записей, которые будут перезаписаны, если сделать это таким образом.

2. О, я понимаю, что вы имеете в виду, я посмотрю, смогу ли я это исправить.

3. да, вот очень простой пример: если у меня есть dict {a: {b: {c: 1}, d: {e: 1}}} и я добавляю записи из «a / f / g», тогда я получу dict {a:{f:{g:1}}}. все остальные записи, такие как b, c, d, e, будут «перезаписаны»

4. Я понял это, я пытался использовать is для проверки типа значения, а это не то, что is нужно; Я отредактировал ответ, и теперь код должен работать.

5. @Omnikar согласно @Nik если вы используете это dict , то ваш вывод будет неправильным.

Ответ №2:

Я принял такое dict решение, что вы должны изменить его в соответствии с вашими требованиями. Я взял path = 'Folder1/Folder12_/Folder121/File1211' where Folder12_ отсутствует в супердиректории.

 df = {
    'Folder1': {
        'Folder11': {
            'File111': 1,
            'File112': 1,
        },
        'Folder12': {
            'Folder121': {
                'File1211': 1,
                'File1212': 1,
            }
        }
    }
}
 

 path = 'Folder1/Folder12_/Folder121/File1211'.split('/')

df_test = df
ind_last = 0
for i in path:
    ind_last = path.index(i)
    if df_test.get(i):
        df_test = df_test.get(i)
    else:
        break

for i in path[ind_last:]:
    if path.index(i) != 3:
        df_test[i] = {}
        df_test = df_test.get(i)
    else:
        df_test[i] = 1
        df_test = df_test.get(i)
print(df)