Я не знаю, почему вы хотите это сделать, такого рода вещи будет медленным, когда размер увеличивается структуры данных. Вероятно, было бы лучше иметь плоский словарь, однако алгоритм выравнивания должен быть определен.
Я сделал что-то грубое для того, что, я думаю, вы хотите. Метод flatten
возвращает что-то похожее на items
(список кортежей (ключ, значение)), где «ключ» на самом деле является кортежем ключей. Это необходимо, поскольку словари могут содержать один и тот же ключ, поэтому при преобразовании в плоское пространство имен (которое требует уникальных ключей) возникает конфликт.
class recurdict(dict):
'''
Recursive Dictionary
'''
def __init__(self, idict=None, **kwargs):
dict.__init__(self)
if idict is not None:
self.update(idict)
if len(kwargs):
self.update(kwargs)
def __contains__(self, key):
return (key in self.keys())
def __getitem__(self, key):
if self.__contains__(key):
return self.___getitem__(self, key)
else:
raise KeyError(key)
@staticmethod
def ___getitem__(idict, key):
if dict.__contains__(idict, key):
return dict.__getitem__(idict, key)
else:
result = None
for k, v in idict.iteritems():
if hasattr(v, "keys"):
result = recurdict.___getitem__(v, key)
if(result):
return result
else:
continue
def flatten(self):
return self._flatten(self)
@staticmethod
def _flatten(idict, key_chain = []):
found_keys = []
for k, v in idict.iteritems():
if hasattr(v, "keys"):
found_keys.extend(recurdict._flatten(v, key_chain + [k]))
else:
found_keys.append((tuple(key_chain + [k]), v))
return found_keys
def has_key(self, key):
return self.__contains__(key)
def keys(self):
return self._keys(self)
@staticmethod
def _keys(idict):
found_keys = dict.keys(idict)
for k, v in idict.iteritems():
if hasattr(v, "keys"):
found_keys.extend(recurdict._keys(v))
return found_keys
def update(self, other=None, **kwargs):
if other is None:
pass
elif hasattr(other, "iteritems"):
for k, v in other.iteritems():
self.__setitem__(k,v)
elif hasattr(other, "keys"):
for k in other.keys():
self.__setitem__(k,other.__getitem__(k))
else:
for k, v in other:
self.__setitem__(k,v)
if kwargs:
self.update(kwargs)
example_dict = recurdict\
({
"key1" : "value1",
"key2" : "value2",
"key3" :
{
"key3a": "value3a"
},
"key4" :
{
"key4a":
{
"key4aa": "value4aa",
"key4ab": "value4ab",
"key4ac":
{
"key4ac1": [0,1,2],
"key4ac2": (3,4,5),
"key4ac3":
[
{
"sub_key_x": 0,
"sub_key_y": 1,
},
6
]
}
},
"key4b": "value4b"
}
})
print example_dict.keys()
print "key1" in example_dict
print "key4ac1" in example_dict
print example_dict["key4ac1"]
for (k, v) in example_dict.flatten():
print (k, v)
спасибо, хорошо работает =) Для того, чтобы ответить на вопрос, почему я хочу это, что я пишу сценарий для маневра через словари (пользователь может выбрать ключ и получить содержание отображается, ..) , который работает до сих пор, но я также хотел реализовать функцию поиска, чтобы быстрее находить некоторые ключи/значения. – BaumKuchen