2 回答

TA貢獻(xiàn)1818條經(jīng)驗(yàn) 獲得超8個(gè)贊
通常生成器函數(shù)會(huì)簡(jiǎn)化這種遍歷。在這里,我們可以編寫一個(gè)非常簡(jiǎn)單的生成器,然后將其包裝在一個(gè)函數(shù)中,該函數(shù)從該生成器創(chuàng)建一個(gè)數(shù)組:
const getPaths = function * (xs, ps = []) {
for (let x of xs) {
yield [... ps, x .attributes .name] .join (' > ')
yield * getPaths (x .children, [...ps, x .attributes .name])
}
}
const categoryNames = (categories) =>
[... getPaths (categories .data)]
const categories = {data: [{type: "categories", id: "1", attributes: {name: "Top Level"}, children: [{type: "categories", id: "2", attributes: {name: "Sub 1"}, children: [{type: "categories", id: "4", attributes: {name: "Sub 1-2"}, children: []}]}, {type: "categories", id: "3", attributes: {name: "Sub 2"}, children: []}]}]};
console .log (
categoryNames(categories)
)
getPaths通過刪除join (' > ')調(diào)用并將其添加map到categoryNames. 但是由于children和attributes.names已經(jīng)是針對(duì)特定問題的,我可能不會(huì)打擾。
解釋
你說你沒有完全遵循這個(gè)代碼。這是試圖解釋它。如果我解釋一些你已經(jīng)理解的東西,請(qǐng)不要生氣。我不清楚到底需要解釋什么。
外部函數(shù)categoryNames是一個(gè)非常小的包裝器getPaths。那個(gè)做所有的工作。
有兩個(gè)重要特征需要注意getPaths:
它是一個(gè)生成器函數(shù),由關(guān)鍵字和參數(shù)列表*之間的function符號(hào)表示。Generator 函數(shù)創(chuàng)建Generator對(duì)象,因?yàn)樗鼈兎?[可迭代協(xié)議],所以可以在諸如let x of generatorand 之類的結(jié)構(gòu)中使用[...generator]。這就是categoryNames將 的輸出getPaths轉(zhuǎn)換為數(shù)組的方式。(順便說一句,可迭代協(xié)議也是for-of循環(huán)中如何getPaths將數(shù)組轉(zhuǎn)換為值序列的方式。)生成器函數(shù)通過yielding 單個(gè)值或使用yield * anotherGenerator單獨(dú)生成另一個(gè)生成器產(chǎn)生的每個(gè)值來工作。在這些yield調(diào)用之間,函數(shù)被掛起,直到請(qǐng)求下一個(gè)值。
它是一個(gè)遞歸函數(shù);函數(shù)體再次調(diào)用同一個(gè)函數(shù),參數(shù)更簡(jiǎn)單。大多數(shù)情況下,在遞歸函數(shù)中,您會(huì)看到一個(gè)顯式的基本情況,當(dāng)輸入足夠簡(jiǎn)單時(shí),直接返回答案而無需遞歸調(diào)用。這里的基本情況是隱含的。Whenxs是一個(gè)空數(shù)組,for-loop永遠(yuǎn)不會(huì)調(diào)用的主體,因此遞歸結(jié)束。
getPaths接受一個(gè)值數(shù)組(xs是我的未知類型值列表的默認(rèn)名稱;nodes也是一個(gè)好名字)并且它接受一個(gè)字符串?dāng)?shù)組,表示層次結(jié)構(gòu)中直到當(dāng)前節(jié)點(diǎn)的路徑。例如,它可能包含["Top Level", "Sub 1"]. 請(qǐng)注意,這是一個(gè)默認(rèn)參數(shù);如果你不提供它,它會(huì)得到一個(gè)空數(shù)組。
我們遍歷提供給我們的值。對(duì)于每一個(gè),我們首先通過在它們之間穿插來產(chǎn)生組合當(dāng)前路徑和我們當(dāng)前對(duì)象name的attribute屬性的結(jié)果" > "。然后我們通過傳遞孩子和包括當(dāng)前名字在內(nèi)的一組名稱來遞歸,依次產(chǎn)生它的每個(gè)孩子。這個(gè)版本的性能可能稍高一些,也更容易閱讀:
const getPaths = function * (xs, paths = []) {
for (let x of xs) {
const newPaths = [... paths, x .attributes .name]
yield newPaths .join (' > ')
yield * getPaths (x .children, newPaths)
}
}
如果你愿意,你可以這樣定義newPaths:
const newPaths = paths .concat (node .attributes .name)
我希望這有幫助。如果您對(duì)此有任何疑問,請(qǐng)?zhí)砑釉u(píng)論。

TA貢獻(xiàn)1797條經(jīng)驗(yàn) 獲得超4個(gè)贊
看這塊
categories.forEach(c => {
this.res[stackCounter] = { name: c.attributes.name, id: c.id };
});
你可以看到它res[stackCounter]總是被 的最后一個(gè)元素覆蓋categories。要解決這個(gè)問題,也res[stackCounter]應(yīng)該是一個(gè)數(shù)組。
parseCategories(categories, stackCounter = 0) {
// init res[stackCounter]
if (this.res[stackCounter]) {
this.res[stackCounter] = [];
}
categories.forEach(c => {
this.res[stackCounter].push({ name: c.attributes.name, id: c.id }); // push to res[stackCounter]
if(c.children.length >= 1) {
this.parseCategories(c.children, stackCounter + 1);
}
});
return this.res;
}
添加回答
舉報(bào)