2014-10-16 2 views
2

У меня есть словарь в python. Назовем это dict. Этот объект может содержать другой словарь, который, в свою очередь, может содержать другой словарь и т. Д.Как получить ключи от вложенного словаря произвольной длины в Python

 dict = { 'k': v, 'k1': v1, 'dict2':{'k3': v3, 'k4':v4} , 'dict3':{'k5':v5, dict4:{'k6':v6}}} 

Это всего лишь пример. Длина внешнего словаря может быть любой. Я хочу извлечь ключи из такого словарного объекта двумя способами:

  1. получить список только ключей.

    [k,k1,k2,k3,k4,k5,k6] 
    
  2. получить список ключей и его родительский связанный словарь, так что-то вроде этого:

    outer_dict_keys = [k ,dict2, dict3] 
    dict2_keys = [k3,k4] 
    dict3_keys = [k5, dict4] 
    dict4_keys = [k6] 
    

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

Что является лучшим способом достижения вышеуказанного результата?

ответ

3

Используйте смесь итераций и рекурсии хвоста. После цитирования неопределенных имен, форматирования интервалов и удаления «k2» из первого результата, я придумал код ниже. (Написано и проверено на 3.4, оно должно работать на любом 3.x и может на 2.7.) Важно помнить, что порядок итераций dicts по существу случайен и зависит от каждого прогона. Рекурсия, сделанная здесь, посещает субтиметры в глубину-сначала, а не в порядке ширины. Для dict0 оба одинаковы, но если dict4 были вложены в dict2, а не dict3, их не было бы.

dict0 = {'k0': 0, 'k1': 1, 'dict2':{'k3': 3, 'k4': 4}, 
     'dict3':{'k5': 5, 'dict4':{'k6': 6}}} 

def keys(dic, klist=[]): 
    subdics = [] 
    for key in sorted(dic): 
     val = dic[key] 
     if isinstance(val, dict): 
      subdics.append(val) 
     else: 
      klist.append(key) 
    for subdict in subdics: 
     keys(subdict, klist) 
    return klist 

result = keys(dict0) 
print(result, '\n', result == ['k0','k1','k3','k4','k5','k6']) 

def keylines(dic, name='outer_dict', lines=[]): 
    vals = [] 
    subdics = [] 
    for key in sorted(dic): 
     val = dic[key] 
     if isinstance(val, dict): 
      subdics.append((key,val)) 
     else: 
      vals.append(key) 
    vals.extend(pair[0] for pair in subdics) 
    lines.append('{}_keys = {}'.format(name, vals)) 
    for subdict in subdics: 
     keylines(subdict[1], subdict[0], lines) 
    return lines 

result = keylines(dict0) 
for line in result: 
    print(line,) 
print() 
expect = [ 
     "outer_dict_keys = ['k0', 'k1', 'dict2', 'dict3']", 
     "dict2_keys = ['k3', 'k4']", 
     "dict3_keys = ['k5', 'dict4']", 
     "dict4_keys = ['k6']"] 
for actual, want in zip(result, expect): 
    if actual != want: 
     print(want) 
     for i, (c1, c2) in enumerate(zip(actual, want)): 
      if c1 != c2: 
       print(i, c1, c2) 
+0

Это фантастика. Спасибо Терри! – GoldenPlatinum