简体   繁体   English

在这种情况下如何按键对对象数组进行分组

[英]How to group an array of objects by key in this case

Does anyone know of a way to group an array of objects by an object key then create a new array of objects based on the grouping?有谁知道通过对象键对对象数组进行分组然后根据分组创建新的对象数组的方法吗? For example, I have an array of menu objects:例如,我有一个菜单对象数组:

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'},
]

I want to make a new array of menu objects that's grouped by parentId我想创建一个按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'},
]

UPDATE this is my code:更新这是我的代码:

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)
    }
 })

You can use reduce .您可以使用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);

EDIT: This will only add the children on a single level.编辑:这只会在一个级别上添加孩子。 For multiple levels of nesting, you should probably do recursion.对于多层嵌套,您可能应该进行递归。

You can achieve this using Array.reduce easily.您可以使用Array.reduce轻松实现这一点。

Here I have demonstrated a case where you have multi level of nesting.在这里,我展示了一个具有多级嵌套的案例。 That is you can have child nodes inside a child node.也就是说,您可以在子节点内拥有子节点。 If you have only one level of nesting you can use the commented loginc in the code for finding the parent node.如果您只有一层嵌套,您可以使用代码中带注释的 loginc 来查找父节点。

See code comments for implementation details.有关实现细节,请参阅代码注释。

 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);

 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM