简体   繁体   English

在Python中像字典一样在树中遍历

[英]Traversing Down in a tree like dictionary in Python

I have a dictionary something like this: 我有一本这样的字典:

{'A': [12343,
  2342349,
  {'B': [3423,
    342349283,
    73,
    {'C': [-23,
      -2342342,
      36],
     'D': [-2,
      -2520206,
      63]}],
   'E': [-1.5119711426000446,
    -1405627.5262916991,
    26.110728689275614,
    {'F': [-1.7211282679440503,
      -1601770.8149339128,
      113.9541439658396],
     'G': [0.21282003105839883,
      196143.28864221353,
      -13.954143965839597,
      {'H': [0.43384581412426826,
        399408,
        203],
       'I': [-0.22,
        -203265,
        -103]}]}]}]}

I want a function using which I can get values. 我想要一个可以用来获取值的函数。 example, traverse(dictionary,'F') and it should give me the output. 例如traverse(dictionary,'F') ,它应该给我输出。 Couldn't found any solution. 找不到任何解决方案。 I am able to traverse 1 or two level, but not more. 我能够遍历1或2个级别,但不能更多。 Either the code will break or it will not stop. 代码将中断或不会停止。

My Current solution which is not working is: 我当前无法解决的解决方案是:

def traverse(dictionary,search):
    print "Traversing"
    if isinstance(dictionary,dict):
        keys = dictionary.keys()
        print keys
        if search in keys:
            print "Found",search,"in",keys
            print "Printing found dict",dictionary
            print
            print "Check this out",dictionary.get(search)
            print "Trying to return"
            val=dictionary.get(search)
            return val
        else:
            for key in keys:
                print 'Key >>>>>>>>>',dictionary.get(key)
                print
                temp=dictionary.get(key)[-1]
                print "Temp >>>>>>>",temp
                traverse(temp,search)

You need to handle both dictionaries and lists to traverse your structure entirely. 您需要同时处理字典和列表,才能完全遍历您的结构。 You currently only handle dictionaries, but the dictionary with the 'F' key in it is an element of a list object, so you can't find it with your method. 您目前仅处理字典,但是其中带有'F'键的字典是列表对象的元素,因此您无法通过方法找到它。

While you can use recursion to make use of the function call stack to track the different levels of your structure, I'd do it iteratively and use a list or collections.deque() (faster for this job) to do track the objects still to process. 虽然您可以使用递归来利用函数调用堆栈来跟踪结构的不同级别,但我还是要进行迭代,并使用list或collections.deque() (此工作更快)来跟踪对象处理。 That's more efficient and won't run into recursion depth errors for larger structures. 这样会更高效,并且不会遇到较大结构的递归深度错误。

For example, walking all the elements with a generator function, then yielding each element visited, could be: 例如,使用生成器函数遍历所有元素,然后产生所访问的每个元素,可能是:

from collections import deque

def walk(d):
    queue = deque([d])
    while queue:
        elem = queue.popleft()
        if isinstance(elem, dict):
            queue.extend(elem.values())
        elif isinstance(elem, list):
            queue.extend(elem)
        yield elem

The above uses a queue to process elements breath first; 上面使用队列先处理元素呼吸; to use it as a stack, just replace queue.popleft() with queue.pop() . 要将其用作堆栈,只需将queue.popleft()替换为queue.pop()

You can then use the above walker to find your elements: 然后,您可以使用上面的walker查找元素:

def search_key(obj, key):
    for elem in walk(obj):
        if isinstance(elem, dict) and key in elem:
            return elem

For your dictionary, the above returns the first dictionary that contains the looked-for key: 对于您的字典,上面的代码返回包含查找关键字的第一个字典:

>>> search_key(dictionary, 'F')
{'F': [-1.7211282679440503, -1601770.8149339128, 113.9541439658396], 'G': [0.21282003105839883, 196143.28864221353, -13.954143965839597, {'H': [0.43384581412426826, 399408, 203], 'I': [-0.22, -203265, -103]}]}
>>> _['F']
[-1.7211282679440503, -1601770.8149339128, 113.9541439658396]

If you are only ever interested in the value for the given key, just return that, of course: 如果您只对给定键的值感兴趣,请当然返回:

def search_key(obj, key):
    for elem in walk(obj):
        if isinstance(elem, dict) and key in elem:
            return elem[key]

Assuming there's going to be only one matching key in any of your given data structure, you can use a function that recursively traverses the dictionary looking for the key and returning its value if found, and if not found it will raise an exception, so that the calling frame can catch it and move on to the next candidate key: 假设任何给定的数据结构中只有一个匹配键,则可以使用一个函数来递归地遍历字典以查找键并返回其值(如果找到),如果找不到,则会引发异常,因此调用框架可以捕获它并继续前进到下一个候选键:

def traverse(dictionary, search):
    for k, v in dictionary.items():
        if k == search:
            return v
        if isinstance(v[-1], dict):
            try:
                return traverse(v[-1], search)
            except ValueError:
                pass
    raise ValueError("Key '%s' not found" % search)

so that traverse(d, 'F') returns (assuming your dict is stored as variable d ): 因此traverse(d, 'F')返回(假设您的字典存储为变量d ):

[-1.7211282679440503, -1601770.8149339128, 113.9541439658396]

On the other hand, if there can be multiple matches in the given data, you can make the function yield the value of a matching key instead so that the function becomes a generator that generates sub-lists of 0 to many matching keys: 另一方面,如果给定数据中可以有多个匹配项,则可以使该函数产生匹配键的值,从而使该函数成为生成器,生成0到许多匹配键的子列表:

def traverse(dictionary, search):
    for k, v in dictionary.items():
        if k == search:
            yield v
        if isinstance(v[-1], dict):
            yield from traverse(v[-1], search)

so that list(traverse(d, 'F')) returns: 这样list(traverse(d, 'F'))返回:

[[-1.7211282679440503, -1601770.8149339128, 113.9541439658396]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM