2015-09-18 2 views
1

Очень странно, что никто этого не спрашивал раньше. Я не могу найти ответа на это в Интернете. У меня есть вложенный dictionnary, и мне нужен список всех его значений (не вложенный список). Это мой код:Получить значения из вложенного словаря в список

dico = { 
    "Balance": { 
     "Normal": { 
      "P1x": 0.889, 
      "P1y": 700.0, 
      "P2x": 0.889, 
      "P2y": 884.0, 
      "P3x": 1.028, 
      "P3y": 1157.0, 
      "P4x": 1.201, 
      "P4y": 1157.0, 
      "P5x": 1.201, 
      "P5y": 700.0 
     }, 
     "Utility": { 
      "P1x": 0.889, 
      "P1y": 700.0, 
      "P2x": 0.889, 
      "P2y": 884.0, 
      "P3x": 0.947, 
      "P3y": 998.0, 
      "P4x": 1.028, 
      "P4y": 998.0, 
      "P5x": 1.028, 
      "P5y": 700.0, 
     } 
    } 
} 

def grab_children(father): 
    local_list = [] 
    for key, value in father.items(): 
     local_list.append(value) 
     local_list.extend(grab_children(father[key])) 
    return local_list 

print(grab_children(dico)) 

dictionnary это нормально гораздо дольше и содержат строки, логические, целые числа и поплавки.
Когда я попробовать свои функции, он сказал AttributeError: 'str' object has no attribute 'items'

Я понимаю, почему, но я не вижу, как это исправить ... Вы можете мне помочь?
Спасибо!

+0

Ваша рекурсия неверна, потому что она никогда не заканчивается без ошибки: когда значение представляет собой строку, а не другой вложенный dict, вы все равно передаете ее в 'grab_children()'. Вы должны остановить рекурсию, когда значение не является dict. – dsh

ответ

1

Вы можете попробовать:

import collections 

def walk(node): 
    for key, item in node.items(): 
     if isinstance(item, collections.Mapping): 
      print(key) 
      walk(item) 
     else: 
      print('\t',key, item) 

С вашего примера, печатает:

Balance 
Utility 
    P3y 998.0 
    P1x 0.889 
    P5x 1.028 
    P5y 700.0 
    P2x 0.889 
    P1y 700.0 
    P2y 884.0 
    P4x 1.028 
    P3x 0.947 
    P4y 998.0 
Normal 
    P3y 1157.0 
    P1x 0.889 
    P5x 1.201 
    P5y 700.0 
    P2x 0.889 
    P1y 700.0 
    P2y 884.0 
    P4x 1.201 
    P3x 1.028 
    P4y 1157.0 

Под Python 3.3+, вы можете сделать:

def walk(node): 
    for key, value in node.items(): 
     if isinstance(value, collections.Mapping): 
      yield from walk(value) 
     else: 
      yield key, value 

>>> list(walk(dico)) 
[('P5y', 700.0), ('P2y', 884.0), ('P4y', 1157.0), ('P4x', 1.201), ('P1x', 0.889), ('P3y', 1157.0), ('P2x', 0.889), ('P1y', 700.0), ('P3x', 1.028), ('P5x', 1.201), ('P5y', 700.0), ('P2y', 884.0), ('P4y', 998.0), ('P4x', 1.028), ('P1x', 0.889), ('P3y', 998.0), ('P2x', 0.889), ('P1y', 700.0), ('P3x', 0.947), ('P5x', 1.028)] 

Тогда если вы ТОЛЬКО нужны значения:

def walk(node): 
    for key, value in node.items(): 
     if isinstance(value, collections.Mapping): 
      yield from walk(value) 
     else: 
      yield value  

>>> list(walk(dico)) 
[700.0, 0.889, 0.889, 998.0, 1.028, 0.947, 700.0, 884.0, 998.0, 1.028, 700.0, 0.889, 0.889, 1157.0, 1.201, 1.028, 700.0, 884.0, 1157.0, 1.201] 

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

+0

О да, это правда, у Python dicts нет никакого порядка ... Так что не имеет смысла помещать значения в список ... Спасибо в любом случае! – Wizix

+0

Получение всех значений имеет свое применение, например тестирование на наличие значения во всех вложенных dicts, вы можете создать набор из них 'vals = set (walk (dict))' и сможете тестировать 'somethings в vals 'например. – dawg

1
def grab_children(father): 
    local_list = [] 
    for key, value in father.items(): 
     local_list.append(key) 
     local_list.append(value) 
    return local_list 
print(grab_children(dico)) 
Смежные вопросы