撰寫一個遞回函式makeTree(categories, parent),該函式接受一組類別物件,每個類別物件都有一個 id 屬性和一個父屬性,并使用父屬性來構造樹回傳這些物件的嵌套樹。
父值 null 表示您位于樹的底部并且該類別沒有父級,因此如果未提供父級,則默認值 parent 為 null。
示例 1:
給定一組具有 id 屬性的物件來創建我們的樹:
const categories1 = [
{ id: 'animals', 'parent': null },
{ id: 'mammals', 'parent': 'animals' }
];
const tree1 = makeTree(categories1, null);
我們應該像這樣回傳一棵樹:
{
animals: {
mammals: {}
}
}
示例 2:現在假設我們有一個回傳一堆資料行的資料庫:
const categories2 = [
{ id: 'animals', 'parent': null },
{ id: 'mammals', 'parent': 'animals' },
{ id: 'cats', 'parent': 'mammals' },
{ id: 'dogs', 'parent': 'mammals' },
{ id: 'chihuahua', 'parent': 'dogs' },
{ id: 'labrador', 'parent': 'dogs' },
{ id: 'persian', 'parent': 'cats' },
{ id: 'siamese', 'parent': 'cats' }
];
然后我們呼叫帶有類別的函式:
const tree2 = makeTree(categories2, null);
上面的呼叫應該回傳下面的樹:
{
animals: {
mammals: {
dogs: {
chihuahua: {},
labrador: {}
},
cats: {
persian: {},
siamese: {}
}
}
} }
I have written ten different things but this is an example of one of my current failures, This is a practice problem but I cannot figure it out at all. I am not sure how to check through the second example object and find the correct keys to put everything in its place. I have thought about iterating backwards to create the individual animals and then place them into the parent objects one by one, but I cannot think of a way to do so.
const makeTree = (categories, parent,obj={}) =>
{
if (categories.length === 0) return obj;
let nextObj = categories[0];
if (nextObj['parent'] === null) obj[nextObj['id']] = {};
else {
var cKey = nextObj['id'];
obj[nextObj['parent']] = Object.assign(cKey);
}
categories.shift();
return makeTree(categories, parent, obj);
};
uj5u.com熱心網友回復:
您實際上不需要在這里遞回,您可以簡單地reduce()跟蹤一個物件(或Map)中的每個節點的陣列,最終樹將是屬性持有的物件,該null屬性將保存所有頂級父級。
我打亂了源陣列,因為陣列的順序無關緊要。
我還記錄了在 reduce 中使用的整個“結果”物件,它是一個平面物件,允許您訪問每個節點而無需擔心它的嵌套深度。此物件要求您在每次迭代中檢索/分配parent和child節點。
原來的
const categories2 = [
{ id: 'dogs', parent: 'mammals' },
{ id: 'siamese', parent: 'cats' },
{ id: 'labrador', parent: 'dogs' },
{ id: 'animals', parent: null },
{ id: 'cats', parent: 'mammals' },
{ id: 'mammals', parent: 'animals' },
{ id: 'chihuahua', parent: 'dogs' },
{ id: 'persian', parent: 'cats' },
];
const result = categories2.reduce((map, { id: child, parent }) => {
const _parent = (map[parent] ??= {});
const _child = (map[child] ??= {});
_parent[child] = _child;
return map;
}, {});
const tree = result[null];
console.log('final tree: ', JSON.stringify(tree, null, 2));
// Logging the entire 'result' object shows the flat object that allows you to access each node without worrying about how deeply nested it is.
console.log('complete result object: ', JSON.stringify(result, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
注意:如果使用邏輯空賦值 (??=) 給您帶來問題,可以用 OR (||) 短路替換
// const _parent = (map[parent] ??= {});
// const _child = (map[child] ??= {});
const _parent = map[parent] || (map[parent] = {});
const _child = map[child] || (map[child] = {});
編輯:更明確的語法
這是對上述內容的重構,但使用了一個for...of回圈,在沒有添加reduce(). 否則邏輯不變,只是它使用兩個物件而不是一個物件——一個用作我們將所有屬性分配給null父項的最終樹,第二個用作所有節點的索引以幫助構建樹。
顯示代碼片段
const categories2 = [
{ id: 'dogs', parent: 'mammals' },
{ id: 'siamese', parent: 'cats' },
{ id: 'labrador', parent: 'dogs' },
{ id: 'animals', parent: null },
{ id: 'cats', parent: 'mammals' },
{ id: 'mammals', parent: 'animals' },
{ id: 'chihuahua', parent: 'dogs' },
{ id: 'persian', parent: 'cats' },
];
const result = {};
const map = {};
for (const { id: child, parent } of categories2) {
if (map[parent] === undefined) {
map[parent] = {};
}
if (map[child] === undefined) {
map[child] = {};
}
map[parent][child] = map[child];
if (parent === null) {
result[child] = map[child];
}
}
console.log('result object: ', JSON.stringify(result, null, 2));
// Logging the result.map shows the flat object that allows you to access each node without worrying about how deeply nested it is.
console.log('node map used in reduce: ', JSON.stringify(map, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
uj5u.com熱心網友回復:
一個完整的遞回解決方案,帶有測驗。
// tree.js
function rootId(nodes) {
return nodes.find((e) => e.parent === null).id;
}
function childIds(categories, parentId) {
return categories.filter((c) => c.parent === parentId).map((c) => c.id);
}
function makeTree(categories, currentId) {
if (currentId === null) {
let rid = rootId(categories);
return { [rid]: makeTree(categories, rid) };
} else {
let tree = {};
childIds(categories, currentId).forEach((childId) => {
tree[childId] = makeTree(categories, childId);
});
return tree;
}
}
module.exports = makeTree;
// tree.test.js
const makeTree = require("./tree");
test("example 1", () => {
const categories = [
{ id: "animals", parent: null },
{ id: "mammals", parent: "animals" },
];
expect(makeTree(categories, null)).toStrictEqual({
animals: {
mammals: {},
},
});
});
test("example 2", () => {
const categories = [
{ id: "animals", parent: null },
{ id: "mammals", parent: "animals" },
{ id: "cats", parent: "mammals" },
{ id: "dogs", parent: "mammals" },
{ id: "chihuahua", parent: "dogs" },
{ id: "labrador", parent: "dogs" },
{ id: "persian", parent: "cats" },
{ id: "siamese", parent: "cats" },
];
expect(makeTree(categories, null)).toStrictEqual({
animals: {
mammals: {
dogs: {
chihuahua: {},
labrador: {},
},
cats: {
persian: {},
siamese: {},
},
},
},
});
});
// package.json
{
"name": "tree_js",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"jest": "^27.3.1",
"prettier": "^2.4.1"
},
"scripts": {
"test": "jest"
}
}
運行測驗yarn test。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/347890.html
標籤:javascript object
