簡體   English   中英

在Python中像字典一樣在樹中遍歷

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

我有一本這樣的字典:

{'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]}]}]}]}

我想要一個可以用來獲取值的函數。 例如traverse(dictionary,'F') ,它應該給我輸出。 找不到任何解決方案。 我能夠遍歷1或2個級別,但不能更多。 代碼將中斷或不會停止。

我當前無法解決的解決方案是:

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)

您需要同時處理字典和列表,才能完全遍歷您的結構。 您目前僅處理字典,但是其中帶有'F'鍵的字典是列表對象的元素,因此您無法通過方法找到它。

雖然您可以使用遞歸來利用函數調用堆棧來跟蹤結構的不同級別,但我還是要進行迭代,並使用list或collections.deque() (此工作更快)來跟蹤對象處理。 這樣會更高效,並且不會遇到較大結構的遞歸深度錯誤。

例如,使用生成器函數遍歷所有元素,然后產生所訪問的每個元素,可能是:

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

上面使用隊列先處理元素呼吸; 要將其用作堆棧,只需將queue.popleft()替換為queue.pop()

然后,您可以使用上面的walker查找元素:

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

對於您的字典,上面的代碼返回包含查找關鍵字的第一個字典:

>>> 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]

如果您只對給定鍵的值感興趣,請當然返回:

def search_key(obj, key):
    for elem in walk(obj):
        if isinstance(elem, dict) and key in elem:
            return elem[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)

因此traverse(d, 'F')返回(假設您的字典存儲為變量d ):

[-1.7211282679440503, -1601770.8149339128, 113.9541439658396]

另一方面,如果給定數據中可以有多個匹配項,則可以使該函數產生匹配鍵的值,從而使該函數成為生成器,生成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)

這樣list(traverse(d, 'F'))返回:

[[-1.7211282679440503, -1601770.8149339128, 113.9541439658396]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM