从具有嵌套字段的对象数组创建对象数组 JavaScript/es6

发布于 2025-01-17 06:50:35 字数 869 浏览 3 评论 0原文

我正在处理具有嵌套属性的对象数组,有没有办法编写递归函数来实现下面提到的输出

const firstArray = [
  {
    groupId: '1',
    childRows: [
      {
        groupId: '1a',
        childRows: ['abc', 'def'],
      },
      {
        groupId: '1b',
        childRows: ['pqr', 'xyz'],
      },
    ],
  },
  {
    groupId: '2',
    childRows: [
      {
        groupId: '2a',
        childRows: ['abz', 'dxy'],
      },
      {
        groupId: '2b',
        childRows: ['egh', 'mno'],
      },
    ],
  },
];

如何在 es6 中编写函数以便返回以下输出

[
  { groupId: '1', childRows: ['abc', 'def', 'pqr', 'xyz'] },
  { groupId: '1a', childRows: ['abc', 'def'] },
  { groupId: '1b', childRows: ['pqr', 'xyz'] },
  { groupId: '2', childRows: ['abz', 'dxy', 'egh', 'mno'] },
  { groupId: '2a', childRows: ['abz', 'dxy'] },
  { groupId: '2b', childRows: ['egh', 'mno'] },
];

I am working on an array of objects which has nested attributes, Is there any way to write a recursive function to achieve below output mentioned

const firstArray = [
  {
    groupId: '1',
    childRows: [
      {
        groupId: '1a',
        childRows: ['abc', 'def'],
      },
      {
        groupId: '1b',
        childRows: ['pqr', 'xyz'],
      },
    ],
  },
  {
    groupId: '2',
    childRows: [
      {
        groupId: '2a',
        childRows: ['abz', 'dxy'],
      },
      {
        groupId: '2b',
        childRows: ['egh', 'mno'],
      },
    ],
  },
];

How to write a function in es6 such that below output is returned

[
  { groupId: '1', childRows: ['abc', 'def', 'pqr', 'xyz'] },
  { groupId: '1a', childRows: ['abc', 'def'] },
  { groupId: '1b', childRows: ['pqr', 'xyz'] },
  { groupId: '2', childRows: ['abz', 'dxy', 'egh', 'mno'] },
  { groupId: '2a', childRows: ['abz', 'dxy'] },
  { groupId: '2b', childRows: ['egh', 'mno'] },
];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

番薯 2025-01-24 06:50:35

我找到了解决方案。我试图用代码中的注释来解释你

const firstArray = [
    {
      groupId: '1',
      childRows: [
        {groupId: '1a',childRows: ['abc', 'def']},
        {groupId: '1b',childRows: ['pqr', 'xyz']}
      ]
    },
    {
      groupId: '2',
      childRows: [
        {groupId: '2a',childRows: ['abz', 'dxy']},
        { groupId: '2b',childRows: ['egh', 'mno']}
      ]
    },
];

function solution (arr){
  const result = [] 

  for (let i = 0; i < arr.length ; i++) {
  
      let parent = [] // this is where I will accumulate all the "childRows" of the same parent
      
      let oldResultLengt = result.length // remember this for now
      
      for (let j = 0; j < arr[i].childRows.length; j++) {
      
          const _childRows = arr[i].childRows[j].childRows // save the specific child array 
          
          result.push({'groupId':arr[i].childRows[j].groupId, 'childRows': _childRows}) // put the object into result array
          
          parent.push(..._childRows) // add to parent array

      }
      /* in this part of the code, at the first iteration the let result looks this:
      [
        {"groupId": "1a", "childRows": ["abc", "def"]},
        {"groupId": "1b", "childRows": ["pqr", "xyz"]}
      ]
      
    but oldResultLength is still 0, so I use splice to insert the parent element before their own childrens
 */
     result.splice(oldResultLengt, 0, {'groupId' : arr[i].groupId, 'childRows': parent})
  }
  return result
}

console.log(solution(firstArray))

没有注释的函数:

function solution (arr){
  const result = []
  for (let i = 0; i < arr.length ; i++) {
      let parent = []
      let oldResultLengt = result.length
      for (let j = 0; j < arr[i].childRows.length; j++) {
          const _childRows = arr[i].childRows[j].childRows
          result.push({'groupId':arr[i].childRows[j].groupId, 'childRows': _childRows})
          parent.push(..._childRows)
      }
     result.splice(oldResultLengt, 0, {'groupId' : arr[i].groupId, 'childRows': parent})
  }
  return result
}

I found a solution. I tried to explain you with comments in the code

const firstArray = [
    {
      groupId: '1',
      childRows: [
        {groupId: '1a',childRows: ['abc', 'def']},
        {groupId: '1b',childRows: ['pqr', 'xyz']}
      ]
    },
    {
      groupId: '2',
      childRows: [
        {groupId: '2a',childRows: ['abz', 'dxy']},
        { groupId: '2b',childRows: ['egh', 'mno']}
      ]
    },
];

function solution (arr){
  const result = [] 

  for (let i = 0; i < arr.length ; i++) {
  
      let parent = [] // this is where I will accumulate all the "childRows" of the same parent
      
      let oldResultLengt = result.length // remember this for now
      
      for (let j = 0; j < arr[i].childRows.length; j++) {
      
          const _childRows = arr[i].childRows[j].childRows // save the specific child array 
          
          result.push({'groupId':arr[i].childRows[j].groupId, 'childRows': _childRows}) // put the object into result array
          
          parent.push(..._childRows) // add to parent array

      }
      /* in this part of the code, at the first iteration the let result looks this:
      [
        {"groupId": "1a", "childRows": ["abc", "def"]},
        {"groupId": "1b", "childRows": ["pqr", "xyz"]}
      ]
      
    but oldResultLength is still 0, so I use splice to insert the parent element before their own childrens
 */
     result.splice(oldResultLengt, 0, {'groupId' : arr[i].groupId, 'childRows': parent})
  }
  return result
}

console.log(solution(firstArray))

Function without comments:

function solution (arr){
  const result = []
  for (let i = 0; i < arr.length ; i++) {
      let parent = []
      let oldResultLengt = result.length
      for (let j = 0; j < arr[i].childRows.length; j++) {
          const _childRows = arr[i].childRows[j].childRows
          result.push({'groupId':arr[i].childRows[j].groupId, 'childRows': _childRows})
          parent.push(..._childRows)
      }
     result.splice(oldResultLengt, 0, {'groupId' : arr[i].groupId, 'childRows': parent})
  }
  return result
}

つ可否回来 2025-01-24 06:50:35

我想出了这个递归函数。输出对象按预期顺序排列。

const getNestedGroups = (array, groups = []) => {
  const finalArray = [];

  // Group list should be empty as it is filled here.
  groups.length = 0;

  array.forEach((group) => {
    if (group.childRows.length > 0) {
      // If the group does not have nested groups we just append it to the group list.
      if (typeof group.childRows[0] === "string") {
        groups.push(group);
      }
      // If the group has children, the same function is called for them.
      else {
        // Call function for child
        const directChildren = [];
        const childGroups = getNestedGroups(group.childRows, directChildren);

        // Makes an object from the direct children (which were also made from their direct children if they had some).
        let groupWithChildren = { groupId: group.groupId, childRows: [] };
        childGroups.forEach((child) => {
          groupWithChildren.childRows.push(...child.childRows);
        });

        // Adds child to group list.
        groups.push(groupWithChildren);
        groups.push(...directChildren);
      }
    }
  });

  // Adds the new groups to the output array.
  finalArray.push(...groups)
  return finalArray;
}

然后您调用该函数。

console.log(getNestedGroups(firstArray));

这是输出。

[
  { groupId: '1', childRows: [ 'abc', 'def', 'pqr', 'xyz' ] },
  { groupId: '1a', childRows: [ 'abc', 'def' ] },
  { groupId: '1b', childRows: [ 'pqr', 'xyz' ] },
  { groupId: '2', childRows: [ 'abz', 'dxy', 'egh', 'mno' ] },
  { groupId: '2a', childRows: [ 'abz', 'dxy' ] },
  { groupId: '2b', childRows: [ 'egh', 'mno' ] }
]

编辑:感谢 J. Villasmil,我看到我们可以使用 array1.push(...array2) 优化 array1 = array1.concat(array2)。我所以更新了我的答案。

I came up with this recursive function. The output objects are in the intended order.

const getNestedGroups = (array, groups = []) => {
  const finalArray = [];

  // Group list should be empty as it is filled here.
  groups.length = 0;

  array.forEach((group) => {
    if (group.childRows.length > 0) {
      // If the group does not have nested groups we just append it to the group list.
      if (typeof group.childRows[0] === "string") {
        groups.push(group);
      }
      // If the group has children, the same function is called for them.
      else {
        // Call function for child
        const directChildren = [];
        const childGroups = getNestedGroups(group.childRows, directChildren);

        // Makes an object from the direct children (which were also made from their direct children if they had some).
        let groupWithChildren = { groupId: group.groupId, childRows: [] };
        childGroups.forEach((child) => {
          groupWithChildren.childRows.push(...child.childRows);
        });

        // Adds child to group list.
        groups.push(groupWithChildren);
        groups.push(...directChildren);
      }
    }
  });

  // Adds the new groups to the output array.
  finalArray.push(...groups)
  return finalArray;
}

You then call the function.

console.log(getNestedGroups(firstArray));

Here is the output.

[
  { groupId: '1', childRows: [ 'abc', 'def', 'pqr', 'xyz' ] },
  { groupId: '1a', childRows: [ 'abc', 'def' ] },
  { groupId: '1b', childRows: [ 'pqr', 'xyz' ] },
  { groupId: '2', childRows: [ 'abz', 'dxy', 'egh', 'mno' ] },
  { groupId: '2a', childRows: [ 'abz', 'dxy' ] },
  { groupId: '2b', childRows: [ 'egh', 'mno' ] }
]

Edit : Thanks to J. Villasmil, I saw we can optimize array1 = array1.concat(array2) with array1.push(...array2). I so updated my answer.

凑诗 2025-01-24 06:50:35

一个很好的说法是,childRows 属性包含字符串或对象,childRowsIn 函数返回 childRows 的字符串,而 childRowsIn childRows 的对象

function childRowsIn(object) {
  const childRows = (object.childRows || []).filter(e => ['string','object'].includes(typeof e));
  return childRows.map(e =>
    typeof e === 'string'? e: childRowsIn(e)
  ).flat()
}

const object = getData();
console.log(childRowsIn(object))

function getData() {
  const firstArray = [{
      groupId: '1',
      childRows: [{
          groupId: '1a',
          childRows: ['abc', 'def'],
        },
        {
          groupId: '1b',
          childRows: ['pqr', 'xyz'],
        },
      ],
    },
    {
      groupId: '2',
      childRows: [{
          groupId: '2a',
          childRows: ['abz', 'dxy'],
        },
        {
          groupId: '2b',
          childRows: ['egh', 'mno'],
        },
      ],
    },
  ];
  return {
    childRows: firstArray
  };
}

A nice way to say this is that the childRows prop contains either strings or objects, and the childRowsIn function returns the childRows's strings and the childRowsIn the childRows's objects

function childRowsIn(object) {
  const childRows = (object.childRows || []).filter(e => ['string','object'].includes(typeof e));
  return childRows.map(e =>
    typeof e === 'string'? e: childRowsIn(e)
  ).flat()
}

const object = getData();
console.log(childRowsIn(object))

function getData() {
  const firstArray = [{
      groupId: '1',
      childRows: [{
          groupId: '1a',
          childRows: ['abc', 'def'],
        },
        {
          groupId: '1b',
          childRows: ['pqr', 'xyz'],
        },
      ],
    },
    {
      groupId: '2',
      childRows: [{
          groupId: '2a',
          childRows: ['abz', 'dxy'],
        },
        {
          groupId: '2b',
          childRows: ['egh', 'mno'],
        },
      ],
    },
  ];
  return {
    childRows: firstArray
  };
}

寄居人 2025-01-24 06:50:35

使用 flatMapconcatdestructuring 可以简化为

const process = (arr) =>
  arr.flatMap(({ groupId, childRows }) =>
    childRows.concat({
      groupId,
      childRows: childRows.flatMap(({ childRows }) => childRows),
    })
  );

const firstArray = [
  {
    groupId: "1",
    childRows: [
      {
        groupId: "1a",
        childRows: ["abc", "def"],
      },
      {
        groupId: "1b",
        childRows: ["pqr", "xyz"],
      },
    ],
  },
  {
    groupId: "2",
    childRows: [
      {
        groupId: "2a",
        childRows: ["abz", "dxy"],
      },
      {
        groupId: "2b",
        childRows: ["egh", "mno"],
      },
    ],
  },
];

console.log(process(firstArray));

Using flatMap, concat and destructuring can simplify as

const process = (arr) =>
  arr.flatMap(({ groupId, childRows }) =>
    childRows.concat({
      groupId,
      childRows: childRows.flatMap(({ childRows }) => childRows),
    })
  );

const firstArray = [
  {
    groupId: "1",
    childRows: [
      {
        groupId: "1a",
        childRows: ["abc", "def"],
      },
      {
        groupId: "1b",
        childRows: ["pqr", "xyz"],
      },
    ],
  },
  {
    groupId: "2",
    childRows: [
      {
        groupId: "2a",
        childRows: ["abz", "dxy"],
      },
      {
        groupId: "2b",
        childRows: ["egh", "mno"],
      },
    ],
  },
];

console.log(process(firstArray));

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文