当前位置: 首页 > 知识库问答 >
问题:

javascript - 如何将js数组中对象的属性值相等的对象组合成一个新的数组元素,然后返回一个新的数组?

傅旺
2023-11-27

将js数组中对象的属性值相等的对象组合成一个新的数组元素。
可以使用reduce、map等函数

比如:

// 原始数组const arr = [  {title: '标题1', url: 'url', groupId: -1},  {title: '标题2', url: 'url', groupId: 123},  {title: '标题3', url: 'url', groupId: 123},  {title: '标题4', url: 'url', groupId: -1},  {title: '标题5', url: 'url', groupId: 456},  {title: '标题6', url: 'url', groupId: 456},  {title: '标题6', url: 'url', groupId: 789},]// 期望结果const resArr = [  {title: '标题1', url: 'url'},  {groupId: 123, group: [{title: '标题2', url: 'url'}, {title: '标题3', url: 'url'}]},  {title: '标题4', url: 'url'},  {groupId: 456, group: [{title: '标题5', url: 'url'}, {title: '标题6', url: 'url'}]}]

如果 groupId 为-1,则删除其groupId属性,并按顺序将该元素加入新的数组中即可

另外:arr数组中相同groupId的元素在数组中的位置总是相邻的。(groupId为-1的除外)
比如:

// 正例const arr = [  {title: '标题1', url: 'url', groupId: -1},  {title: '标题2', url: 'url', groupId: 123},  {title: '标题3', url: 'url', groupId: 123},  {title: '标题4', url: 'url', groupId: -1},  {title: '标题5', url: 'url', groupId: 456},  {title: '标题6', url: 'url', groupId: 456},  {title: '标题4', url: 'url', groupId: -1},]// 反例const arr = [  {title: '标题1', url: 'url', groupId: -1},  {title: '标题2', url: 'url', groupId: 123},  {title: '标题4', url: 'url', groupId: -1},  {title: '标题3', url: 'url', groupId: 123},  {title: '标题5', url: 'url', groupId: 456},  {title: '标题5', url: 'url', groupId: 789},  {title: '标题6', url: 'url', groupId: 456},]

共有5个答案

寇景明
2023-11-27

感谢 @残梦终将消散 提供的思路,我简写了一下方法。
我使用了数组的 at() 函数,这个函数不支持IE,最低Chrome版本要求 92,也可以使用slice (-1),比 length 有更好的性能

const arr = [  {title: '标题1', url: 'url', groupId: -1},  {title: '标题2', url: 'url', groupId: 123},  {title: '标题3', url: 'url', groupId: 123},  {title: '标题4', url: 'url', groupId: -1},  {title: '标题5', url: 'url', groupId: 456},  {title: '标题6', url: 'url', groupId: 456},  {title: '标题6', url: 'url', groupId: 789},]const resArr = arr.reduce((previous, current) => {  const {title, url, groupId} = current  if (groupId === -1) {    previous.push({title, url})  } else {    // 获取 previous 数组中最后一位元素    const last = previous.at(-1)    if (last.groupId === groupId) {      // 相等,则说明同一groupId的对象元素已经创建      last.group.push({title, url})    } else {      // 不等,则说明还未创建同一groupId的对象元素      previous.push({groupId, group: [{title, url}]})    }  }  return previous}, [])console.log('resArr', resArr)
贝凯
2023-11-27

根据groupid分组这个思路就可以了

const arr = [    { title: '标题1', url: 'url', groupId: -1 },    { title: '标题2', url: 'url', groupId: 123 },    { title: '标题3', url: 'url', groupId: 123 },    { title: '标题4', url: 'url', groupId: -1 },    { title: '标题5', url: 'url', groupId: 456 },    { title: '标题6', url: 'url', groupId: 456 },    { title: '标题4', url: 'url', groupId: -1 },]const fun = (arr) => {    const map = []    arr.forEach(e => {        const copyE = { title: e.title, url: e.url }        if (e.groupId === -1) {            map.push(copyE)        } else {            const findObj = map.find(innerTmp => innerTmp.groupId === e.groupId)            if (findObj) {                findObj.group.push(copyE)            } else {                map.push({ groupId: e.groupId, group: [copyE] })            }        }    })    return map}console.log(JSON.stringify(fun(arr))) // [{"title":"标题1","url":"url"},{"groupId":123,"group":[{"title":"标题2","url":"url"},{"title":"标题3","url":"url"}]},{"title":"标题4","url":"url"},{"groupId":456,"group":[{"title":"标题5","url":"url"},{"title":"标题6","url":"url"}]},{"title":"标题4","url":"url"}]
孟安民
2023-11-27

JavaScript gourpBy

别的语言一般有这个接口,只是 JavaScript 还在提案和实验,要用的话需要加 polyfill

庞修贤
2023-11-27

你可以看看是否满足你需求,reduce的别样用法

算了,我更新一下,直接给groupId取掉了,你看第二次的,第一次我还保留

const arr = [  { title: '标题1', url: 'url', groupId: -1 },  { title: '标题2', url: 'url', groupId: 123 },  { title: '标题3', url: 'url', groupId: 123 },  { title: '标题333', url: 'url', groupId: 123 },  { title: '标题4', url: 'url', groupId: -1 },  { title: '标题5', url: 'url', groupId: 456 },  { title: '标题6', url: 'url', groupId: 456 },]const res = arr.reduce((previous, current) => {  const len = previous.length  const last = len && previous[len - 1]  if (last.groupId === current.groupId) {    // 如果标题4上面还有一个groupId为123的走这个    if (last.group) {      last.group.push({ ...current })    }    else {      previous[len - 1] = {        groupId: last.groupId,        group: [{ ...last }, { ...current }]      }    }  } else {    previous.push(current)  }  return previous}, [])console.log(res)/*[  { "title": "标题1", "url": "url", "groupId": -1 },  {    "groupId": 123,    "group": [      { "title": "标题2", "url": "url", "groupId": 123 },      { "title": "标题3", "url": "url", "groupId": 123 },      { "title": "标题333", "url": "url", "groupId": 123 }    ]  },  { "title": "标题4", "url": "url", "groupId": -1 },  {    "groupId": 456,    "group": [      { "title": "标题5", "url": "url", "groupId": 456 },      { "title": "标题6", "url": "url", "groupId": 456 }    ]  }]*/

-----第二次-----

const arr = [  { title: '标题1', url: 'url', groupId: -1 },  { title: '标题2', url: 'url', groupId: 123 },  { title: '标题3', url: 'url', groupId: 123 },  { title: '标题333', url: 'url', groupId: 123 },  { title: '标题4', url: 'url', groupId: -1 },  { title: '标题5', url: 'url', groupId: 456 },  { title: '标题6', url: 'url', groupId: 456 },]const res = arr.reduce((previous, current) => {  const len = previous.length  const last = len && previous[len - 1]  if (last.groupId === current.groupId) {    // 如果标题4上面还有一个groupId为123的走这个    if (last.group) {      const { groupId: _2, ...currentData } = current      last.group.push({ ...currentData })    }    else {      const { groupId: _1, ...firstData } = last      const { groupId: _2, ...currentData } = current      previous[len - 1] = {        groupId: last.groupId,        group: [{ ...firstData }, { ...currentData }]      }    }  } else {    if (current.groupId === -1) delete current.groupId    previous.push(current)  }  return previous}, [])console.log(res)/*[  { "title": "标题1", "url": "url"},  {    "groupId": 123,    "group": [      { "title": "标题2", "url": "url" },      { "title": "标题3", "url": "url" },      { "title": "标题333", "url": "url" }    ]  },  { "title": "标题4", "url": "url" },  {    "groupId": 456,    "group": [      { "title": "标题5", "url": "url" },      { "title": "标题6", "url": "url" }    ]  }]*/
颛孙正卿
2023-11-27

您可以使用 JavaScript 的 reduce 方法来解决这个问题。reduce 方法会遍历数组中的每一个元素,并且每次都会使用累积值和当前元素进行操作。

以下是一个可能的解决方案:

const arr = [  {title: '标题1', url: 'url', groupId: -1},  {title: '标题2', url: 'url', groupId: 123},  {title: '标题3', url: 'url', groupId: 123},  {title: '标题4', url: 'url', groupId: -1},  {title: '标题5', url: 'url', groupId: 456},  {title: '标题6', url: 'url', groupId: 456},];const resArr = arr.reduce((acc, cur, index) => {  if (index === 0) {    acc.push(cur);  } else {    if (cur.groupId === arr[index - 1].groupId) {      const group = acc[acc.length - 1].group || [];      group.push(cur);      acc[acc.length - 1].group = group;    } else {      acc.push({...cur});    }  }  return acc;}, []);console.log(resArr);

这段代码会创建一个新的数组 resArr。在 reduce 函数中,我们检查当前元素的 groupId 是否与前一个元素的 groupId 相同。如果相同,我们将当前元素添加到前一个元素的 group 数组中。如果不同,我们则将当前元素添加到 resArr 中。这样,我们就可以得到一个新的数组,其中具有相同 groupId 的对象被组合在一起。

 类似资料: