按键创建父词典

时间:2013-09-01 22:06:17

标签: python dictionary parent-child

我在这里有一个这样的指导:

example_dict = { 
    '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'
    }
}

我尝试使用此问题的递归代码创建父词典: Get parents keys from nested dictionary

问题是元组或列表,它们打破了循环。 我想在字典中搜索字符串,使用difflib对匹配结果进行排序。

如果有人有想法/架构如何在字典中搜索创建父词典的键/值,那真的很高兴。

例如:

search_in_dict(example_dict, 'sub key')
# returning the content of:
# example_dict['key4']['key4a']['key4ac']['key4ac3']

亲切的问候BaumKuchen

1 个答案:

答案 0 :(得分:0)

我不知道你为什么要这样做,当数据结构大小增加时,这种类型的东西会变慢。有一个扁平字典可能会更好,但必须定义扁平化算法。

我为你想要的东西做了一些粗糙的事情。 flatten方法返回类似于items((键,值)元组的列表),其中'key'实际上是键的元组。这是必要的,因为字典可能包含相同的键,因此当转换为平面命名空间(需要唯一键)时,就会出现冲突。

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)