我試圖遍歷一個具有任意深度嵌套葉子的物件,獲取每個根節點到葉子的路徑。這方面的一個例子可能是:
class Field (object):
def __init__(self, name, subfields=None):
self.name = name
self.subfields = subfields
f1 = Field("username")
f2 = Field("ip_address")
f3 = Field("song_id")
f11 = Field("song_length")
f10 = Field("misc_attrs", subfields=[f3, f11])
f4 = Field("event_time")
f5 = Field("song_name", subfields=[f1,f2])
f6 = Field("user_song_upload", subfields=[f10])
input_list = [f4,f5,f6]
我的目標是生成一個串列output
串列,其中每個串列都output
代表從根節點到葉子節點的路徑。所以在上面的例子中,我們有以下輸出:
[["event_time"],["song_name","username"],["song_name","ip_address"],["user_song_upload","misc_attrs","song_id"],["user_song_upload","misc_attrs","song_length"]]
我有一個函式可以回傳所有葉節點,但是我無法跟蹤每個節點的完整路徑。這是我到目前為止所擁有的:
def get_leaf_paths(input_list, output = [], path=[]):
for x in input_list:
if not x.subfields:
# we have a leaf
path.append(x.name)
output.append(path)
# next line clears the leaf from our last path
path = path[:-1]
else:
# we don't have a leaf node, and need to iterate on the subfields
path.append(x.name)
get_leaf_paths(x.subfields, output, path)
return output
然而,這會導致路徑構建不正確(例如,兩個相鄰的頂級節點將在輸出中的同一個內部串列中結束:
[['event_time'],
['song_name', 'username', 'user_song_upload', 'misc_attrs', 'song_id'],
['song_name', 'ip_address'],
['song_name', 'username', 'user_song_upload', 'misc_attrs', 'song_id'],
['song_name', 'username', 'user_song_upload', 'misc_attrs', 'song_length']]
uj5u.com熱心網友回復:
您可以構建一個適當的基本案例來簡化代碼。請嘗試以下操作:
def get_leaf_paths(lst):
if not lst: # empty list or None
return [[]]
return [[f.name, *path] for f in lst for path in get_leaf_paths(f.subfields)]
print(get_leaf_paths(input_list))
在代碼中,基本情況是“空串列或無”,即, whensubfields
傳遞給函式但subfields
實際上是None
。在葉節點呼叫函式時就是這種情況。
輸出:
[['event_time'], ['song_name', 'username'], ['song_name', 'ip_address'], ['user_song_upload', 'misc_attrs', 'song_id'], ['user_song_upload', 'misc_attrs', 'song_length']]
uj5u.com熱心網友回復:
如果您需要將其應用于非常深的結構并且遞回(如@j1-lee 在其其他非常干凈的實作中建議)不是一種選擇,則此方法有效:
def get_leaf_paths(lst):
stack, l, i = [], lst, 0
while l and len(l) > i:
if l[i].subfields:
stack.append((l, i))
l, i = l[i].subfields, 0
else:
yield [x[n].name for x, n in stack] [l[i].name]
i = 1
if i >= len(l):
l, i = stack.pop()
i = 1
print(list(get_leaf_paths(input_list)))
結果:
[['event_time'], ['song_name', 'username'], ['song_name', 'ip_address'], ['user_song_upload', 'misc_attrs', 'song_id'], ['user_song_upload', 'misc_attrs', 'song_length']]
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/349175.html