我正在嘗試撰寫類似這樣的功能:
輸入:
['A', '-B1', '--B2', '-C1', 'D']
輸出:
{'A': {'B1': {'B2': {}}, 'C1': {}}, 'D': {}}
如您所見,B1 和 C1 是 A 的孩子,B2 是 B1 的孩子。它可以基于任何級別嵌套-
我為此撰寫了一個 Javascript 代碼,但是在創建孩子時似乎有問題。這是我的代碼:
function fetch_levels(li, chr='-') {
var res_list = []
for (i=0; i<li.length; i ) {
item = li[i]
level = item.length - item.replace(RegExp(`^${chr} `), '').length
key = item.replace(RegExp(`^${chr} `), '')
value = {}
res_list.push({
level: level,
name: key,
value: value
})
}
return res_list
}
function ttree_to_json(ttree, level=0) {
result = {}
for (i = 0; i < ttree.length; i ) {
cn = ttree[i]
nn = ttree[i 1] || {'level': -1}
// Edge cases
if (cn['level'] > level) {
continue
}
if (cn['level'] < level) {
return result
}
// Recursion
if (nn['level'] == level) {
result[cn['name']] = cn['value']
} else if (nn['level'] > level) {
rr = ttree_to_json(ttree.slice(i 1), level=nn['level'])
result[cn['name']] = rr
}
else {
result[cn['name']] = cn['value']
return result
}
}
return result
}
這就是呼叫函式的方式:
console.log(ttree_to_json(fetch_levels(['A', '-B1', '--B2', '-C', 'D'])))
我得到的輸出是這樣的:
Object { B2: {…}, C: {} }
這是錯誤的。
注意:在 python 程式中應用了相同的邏輯,它似乎給出了正確的輸出。我無法弄清楚 JavaScript 出了什么問題。作為參考,我還提到了 Python 程式的作業版本:
def fetch_levels(li: list, split_char='-'):
res_list = []
for item in li:
level = len(item) - len(item.lstrip(split_char))
key = item.lstrip(split_char)
val = {}
res_list.append({'level': level, 'name': key, 'value': val})
return res_list
def ttree_to_json(ttree, level=0):
result = {}
for i in range(0, len(ttree)):
cn = ttree[i]
try:
nn = ttree[i 1]
except:
nn = {'level': -1}
# Edge cases
if cn['level'] > level:
continue
if cn['level'] < level:
return result
# Recursion
if nn['level'] == level:
result[cn['name']] = cn['value']
elif nn['level'] > level:
rr = ttree_to_json(ttree[i 1:], level=nn['level'])
result[cn['name']] = rr
else:
result[cn['name']] = cn['value']
return result
return result
if __name__ == '__main__':
ttree = fetch_levels(['A', '-B1', '--B2', '-C1', 'D'])
result = ttree_to_json(ttree)
print(result)
任何人都可以幫助我弄清楚 JavaScript 代碼有什么問題嗎?
該解決方案的靈感來自此處提到的示例代碼:
uj5u.com熱心網友回復:
您可以通過為嵌套物件的級別參考獲取一個陣列來簡化代碼。
任何屬性都分配給給定的級別(破折號計數),并將物件帶到下一個級別。
const
data = ['A', '-B1', '--B2', '-C1', 'D'],
result = {},
levels = [result];
data.forEach(s => {
let level = 0;
while (s[level] === '-') level ;
s = s.slice(level);
levels[level][s] = levels[level 1] = {};
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
uj5u.com熱心網友回復:
不需要遞回。由于有關要添加(下一個)嵌套級別的唯一可靠資訊由破折號計數攜帶,因此無論如何都可以將下一個級別添加到最近處理的上一個/下一個級別的物件參考中。
因此,陣列形式的查找通過其索引來參考每個最近創建的級別/分支,這是一個簡單的基于回圈的解決方案所需的一切。
下一個提供的實作使用reduce基于方法。
function aggregateObjectHierarchyLevel(
{ recentLevels, result = {} },
item,
idx,
) {
// handle/synchronize the initial `result` reference.
if (idx === 0) {
recentLevels = [result];
}
const [_, dashes = '', key = ''] = item.match(/^([-]*)(.*)/) ?? [];
const level = dashes.length;
recentLevels[level 1] = recentLevels[level][key] = {};
return { recentLevels, result };
};
console.log(
['A', '-B1', '--B2', '-C1', 'D']
.reduce(aggregateObjectHierarchyLevel, {})
.result
)
console.log(
['A', '-B1', '--B2', '---B3', '-C1', 'D']
.reduce(aggregateObjectHierarchyLevel, {})
.result
)
console.log(
['A', '-B1', '--B2', '---B3', '--C2', '---C3', '-D1', 'E']
.reduce(aggregateObjectHierarchyLevel, {})
.result
)
.as-console-wrapper { min-height: 100%!important; top: 0; }
uj5u.com熱心網友回復:
另一個版本,在設計上與 Peter 和 Nina 的非常相似,但編碼風格不同,如下所示:
const nest = (strings, result = {}) => strings .reduce (
(levels, str, _, __, [___, hyphens, val] = str .match (/(\-*)(. )/), lvl = hyphens .length) => (
(levels [lvl] [val] = levels [lvl 1] = {}),
levels
), [result]
) [0]
console .log (nest (['A', '-B1', '--B2', '-C1', 'D']))
我們使用與這兩個答案相同的嵌套結構,并使用與 Peter 類似的正則運算式來分離字串的兩個部分,并使用與這兩個答案相同的更新邏輯。在這里,我們在.reduce呼叫中執行此操作,僅修改隱藏的累加器。
我獨立于那些寫了這個,回來發現已經有兩個很好的答案,但我認為這已經足夠不同了。(我還修復了它以竊取彼得對正則運算式match呼叫的解構。比我原來.slice (1, 3)的 -then-destructure 方法好多了!)
有趣的是,三種截然不同的編碼風格都使用相同的基本設計來解決問題!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/471402.html
標籤:javascript 递归 树 迭代 尾递归
下一篇:匿名遞回函式
