在本例中如何按键对对象数组进行分组



有没有人知道一种方法,通过对象键组对象数组,然后根据分组创建一个新的对象数组?例如,我有一个菜单对象数组:

let menus = [
{id: 1, parentId: 0, text: 'Home'},
{id: 2, parentId: 0, text: 'About'},
{id: 3, parentId: 0, text: 'Product'},
{id: 4, parentId: 3, text: 'Product Category 1'},
{id: 5, parentId: 3, text: 'Product Category 2'},
{id: 6, parentId: 3, text: 'Product Category 3'},
{id: 7, parentId: 0, text: 'Contact'},
{id: 8, parentId: 7, text: 'Contact child 1'},
{id: 9, parentId: 0, text: 'Blog'},
]

我想创建一个新的菜单对象数组,按parentId

分组
[
{id: 1, parentId: 0, text: 'Home'},
{id: 2, parentId: 0, text: 'About'},
{id: 3, parentId: 0, text: 'Product', child: [
{id: 4, parentId: 3, text: 'Product Category 1'},
{id: 5, parentId: 3, text: 'Product Category 2'},
{id: 6, parentId: 3, text: 'Product Category 3'},
]},
{id: 7, parentId: 0, text: 'Contact', child: [
{id: 8, parentId: 7, text: 'Contact child 1'},
]},
{id: 9, parentId: 0, text: 'Blog'},
]

这是我的代码:

let newListMenu = []
menus.forEach(it => {
let childrenData = []
if (it.parentId&& it.parentId!== 0) {
let parent = menus.find(_it => _it.Id == it.parentId)
childrenData.push(it)
parent.child= child
} else {
newListMenu.push(it)
}
})

您可以使用Array.reduce轻松实现此功能。

这里我展示了一个多级嵌套的例子。也就是说,子节点中可以有子节点。如果您只有一层嵌套,您可以在代码中使用注释的登录来查找父节点。

参见代码注释了解实现细节。

const menus = [{ id: 1, parentId: 0, text: 'Home' }, { id: 2, parentId: 0, text: 'About' }, { id: 3, parentId: 0, text: 'Product' }, { id: 4, parentId: 3, text: 'Product Category 1' }, { id: 5, parentId: 3, text: 'Product Category 2' }, { id: 6, parentId: 3, text: 'Product Category 3' }, { id: 7, parentId: 0, text: 'Contact' }, { id: 8, parentId: 7, text: 'Contact child 1' }, { id: 9, parentId: 0, text: 'Blog' }, { id: 10, parentId: 6, text: 'New Node' }];
const findParentNode = (nodes, child) => {
let parent;
// Loop through input array
// Check if the id of any node is matching with the parent id 
nodes.forEach((item) => {
if(item.id === child.parentId) {
parent = item;
return; // Break loop
} else if(item.child && item.child.length) {
// Check the child nodes
const newParent = findParentNode(item.child, child);
parent = newParent ? newParent : parent;
return; // Break loop
}
});
return parent;
}
const groupedMenu = menus.reduce((acc, curr) => {
// Use this if you have one level of nesting.
// const parentNode = acc.find(node => node.id === curr.parentId);

// Find the parent node from the accumulator list and the current node
const parentNode = findParentNode(acc, curr);

// If parent node is found, push the current node to the child node of parent
// Else push the node to accumulator
if (parentNode) {
parentNode.child ? parentNode.child.push(curr) : parentNode.child = [curr] 
} else {
acc.push(curr);
}
return acc;
}, []);
console.log(groupedMenu);

可以使用reduce

const menus = [
{id: 1, parentId: 0, text: 'Home'},
{id: 2, parentId: 0, text: 'About'},
{id: 3, parentId: 0, text: 'Product'},
{id: 4, parentId: 3, text: 'Product Category 1'},
{id: 5, parentId: 3, text: 'Product Category 2'},
{id: 6, parentId: 3, text: 'Product Category 3'},
{id: 7, parentId: 0, text: 'Contact'},
{id: 8, parentId: 7, text: 'Contact child 1'},
{id: 9, parentId: 0, text: 'Blog'},
];
const nested = menus.reduce((acc, item) => {
// if parentId is 0, add to acc.
if (item.parentId === 0) {
return [
...acc,
item,
];
}
// else find the parent.
const parentIndex = acc.findIndex(parent => parent.id === item.parentId);
const parent = acc[parentIndex];
const children = parent.children ?? [];
// update the array item at index.
return Object.assign(
[],
acc,
{
[parentIndex]: {
...parent,
children: [...children, item], // add the item as a child.
},
},
);
}, []);
console.log(nested);

编辑:这将只在单个级别上添加子节点。对于多级嵌套,您可能应该使用递归。

let menus = [
{id: 1, parentId: 0, text: 'Home'},
{id: 2, parentId: 0, text: 'About'},
{id: 3, parentId: 0, text: 'Product'},
{id: 4, parentId: 3, text: 'Product Category 1'},
{id: 5, parentId: 3, text: 'Product Category 2'},
{id: 6, parentId: 3, text: 'Product Category 3'},
{id: 7, parentId: 0, text: 'Contact'},
{id: 8, parentId: 7, text: 'Contact child 1'},
{id: 9, parentId: 0, text: 'Blog'},
]
function getUniqGroupList(data, val) {
var grouped = [];
data.forEach(function (a) {
if (!this[a[val]]) {
this[a[val]] = {
parentId: a[val],
items: []
};
grouped.push(this[a[val]]);
}
this[a[val]].items.push(a);
}, Object.create(null));
return grouped;
}

var d = getUniqGroupList(menus,'parentId');
console.log(d);