簡體   English   中英

遍歷和修改類似於dict結構的樹狀列表

[英]Traversing and modifying a tree-like list of dict structure

我有一個看起來像這樣的結構:

[ {'id': 4, 'children': None},
  {'id': 2, 'children': 
    [ {'id': 1, 'children':
        [ {'id': 6, 'children': None},
          {'id': 5, 'children': None} ]
      },
      {'id': 7, 'children':
        [ {'id': 3, 'children': None} ]
      }
    ]
  }
]

我還有一個選定的ID列表, [4, 5, 6, 7] 我想遍歷列表,並且對於列表中的每個對象,如果選中,則添加值為1selected鍵,如果不是,則添加0

目前我正在使用此函數遞歸執行此操作:

def mark_selected(tree, selected):
    for obj in tree:
        obj['selected'] = 1 if obj['id'] in selected else 0
        if obj['children'] is not None:
            obj['children'] = mark_selected(obj['children'], selected)
    return tree

這似乎工作正常,但我想知道是否有更聰明的方法來做到這一點,可能使用列表理解或生成器。

任何人都可以為此提出更優雅的解決方案嗎?

遞歸非常優雅。 列表推導不適用,因為您正在改變結構,而不是生成新的序列。 對於生成器,您可以編寫DFS或BFS遍歷器。

def dfs(nodes):
    if nodes is not None:
        for node in nodes:
            yield node
            for child in dfs(node['children']):
                yield child

for node in dfs(tree):
    if node['id'] in selected:
        node['selected'] = true

如果要選擇的ID列表很大,那么將ID轉換為具有ID作為鍵的dict將更加高效,這將加速查找( node['id'] in selected )。

selected = dict(zip(selected, selected))

由於您通過修改輸入對象來操作,並且由於對象在Python中具有引用語義,因此您無需在遞歸步驟中返回值或使用返回值。 此外,如果您可以用'[]'替換子項的'None'條目(更好的是,使用整個而不是列表中的元組),那么您可以簡化邏輯 - 您根本不需要基本情況​​,那么,因為你可以遞歸到一個“空樹”,它只會為所有零項運行for循環,即什么都不做 - 這就是你想要的。

和FFS,你為什么不使用Python的內置布爾類型?

def mark_selected(tree, selected):
    for obj in tree:
        obj['selected'] = obj['id'] in selected
        mark_selected(obj['children'], selected)

(哦,你甚至需要按照特定的順序保留孩子嗎?有一個包含'id'鍵的dicts列表是不自然的;有一個dict,其中鍵是id,更有意義值是沒有'id'的dicts。)

我喜歡使用閉包來表示遞歸函數,對於這個例子它並不重要,但你可以節省在遞歸調用中傳遞'selected'的需要。 在更復雜的示例中,您可以在包含函數中保留相當多的狀態以供遞歸使用。

def mark_selected(tree, selected):
    def recur(tree):
        for obj in tree:
                obj['selected'] = 1 if obj['id'] in selected else 0
                if obj['children'] is not None:
                    recur(obj['children'])
    recur(tree)

暫無
暫無

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

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