在数组中合并具有相同id的对象

6

我猜我的问题非常简单,但仍然找不到解决方案。我有一个像这样的数组:

var originalArray = [{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}]

我想将它修改为这个样子(根据id合并并连接元素):
newArray = [{
  id: 1,
  elements: [1, 2, 3, 4]
}, {
  id: 5,
  elements: ['a', 'b', 'c', 'd']
}, {
  id: 27,
  elements: []
}]

我已经尝试了多次,但仍然没有找到一个优雅的方法来做到这一点。


6
你好!请参加[新手导览](你将获得徽章!)并阅读[帮助中心],特别是[如何提出好问题?] (/help/how-to-ask)。你最好的选择是做好调查, 在 SO 上搜索相关主题,然后尝试一下。如果你遇到困难,并且在进行更多研究和搜索后无法解决,请发表一个[最小可重现例子],并明确说明你在哪里遇到了困难。人们很乐意帮忙。 - T.J. Crowder
所以通过查看下面的解决方案,它并不是“死”简单的 ;) - DauleDK
7个回答

8

你可以创建一个以ID为键的对象,并将具有相同ID的元素推送到它们,然后将其转换回数组。对于较大的数组,这比在每次迭代时循环更有效:

var originalArray = [{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}];

const arrayHashmap = originalArray.reduce((obj, item) => {
  obj[item.id] ? obj[item.id].elements.push(...item.elements) : (obj[item.id] = { ...item });
  return obj;
}, {});

const mergedArray = Object.values(arrayHashmap);

console.log(mergedArray);


为什么在JavaScript中使用...? - lalit bhakuni
在 push 中使用 ... 是必要的,如果传递多个项目,或者您可以使用 concat(item.elements),但需要将元素分配给它,因为它返回一个新数组。...item 只是常见的做法,以“打破”原始数组,使得对对象的(浅层)修改不会改变原始数组 - 通常这种不可变编码风格会导致更少的意外副作用,并且还使对象相等比较更加高效和容易,例如 https://reactjs.org/docs/react-api.html#reactpurecomponent 就是由此实现的。 - Dominic

3

试试这段代码:

var originalArray = [{
      id: 1,
      elements: [1, 2]
    },
    {
      id: 1,
      elements: [3, 4]
    },
    {
      id: 5,
      elements: ['a', 'b']
    },
    {
      id: 5,
      elements: ['c', 'd']
    }, {
      id: 27,
      elements: []
    }]
    var newArray = [];
    originalArray.forEach(item => {
       var newItem = {id: item.id, elements: []};
       originalArray.forEach(innerItem => {
          if(innerItem.id == item.id){
              newItem.elements = newItem.elements.concat(innerItem.elements);
          }
       });
      newArray.push(newItem);
    });
    console.log(newArray);

输出:

[{
  id: 1,
  elements: [1, 2, 3, 4]
}, {
  id: 5,
  elements: ['a', 'b', 'c', 'd']
}, {
  id: 27,
  elements: []
}]

2

您可以使用 Array.prototype.reduce() 来创建一个具有 id 属性的对象,使用 Object.values() 获取结果:

const originalArray = [{id: 1, elements: [1, 2]}, {id: 1, elements: [3, 4]}, {id: 5, elements: ['a', 'b']}, {id: 5, elements: ['c', 'd']}, {id: 27, elements: []}]
const objIds = originalArray.reduce((a, { id, elements }) => {
  a[id] = a[id] || {id, elements: []}
  return {...a, ...{[id]: {id, elements: a[id].elements.concat(elements)}}}
}, {})
const result = Object.values(objIds)

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }


1
你可以使用 reduce 函数来实现这个功能:
[{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}].reduce((prev, cur) => {
    const index = prev.findIndex(v => v.id === cur.id);
    if (index === -1) {
       prev.push(cur);
    } else {
        prev[index].elements.push(...cur.elements);
    }
    return prev;
}, [])

1
你可以使用 reduce 方法和 Map 来存储每个 id 的唯一值,然后使用扩展语法 ... 创建一个数组。

var data = [{"id":1,"elements":[1,2]},{"id":1,"elements":[3,4]},{"id":5,"elements":["a","b"]},{"id":5,"elements":["c","d"]},{"id":27,"elements":[]}]

const result = data.reduce((r, {id, elements}) => {
  if(r.get(id)) r.get(id).elements.push(...elements);
  else r.set(id, {id, elements});
  return r;
}, new Map).values();

console.log([...result])


1
您可以使用嵌套的for循环来实现这一点。

var originalArray = [{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}]


for(let i=0;i<originalArray.length;i++){
  let key = originalArray[i].id;
  for(let j=i+1;j<originalArray.length;j++){
    if(originalArray[j].id == key){
      originalArray[i].elements  = [...originalArray[i].elements,...originalArray[j].elements];
      delete originalArray.splice(j,1);
    }

  }
}

console.log(originalArray);


1

这将会生效,并且也相当容易理解。 首先,我们检查新数组中是否已经存在该 id,通过一个在循环外的布尔值来跟踪并在后面进行验证。 此后,如果该 id 的“空间”为空,我们将填充它;否则,该 id 已存在。 因此,我们需要更新它们的元素。我们可以通过首先获取新数组中与初始数组中具有相同 id 的重复对象对应的对象来完成这一点。 然后,我们只需将每个元素从重复项推送到新项即可。


<div data-lang="js" data-hide="false" data-console="true" data-babel="false" class="snippet">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>var originalArray = [{
  id: 1,
  elements: [1, 2]
},
{
  id: 1,
  elements: [3, 4]
},
{
  id: 5,
  elements: ['a', 'b']
},
{
  id: 5,
  elements: ['c', 'd']
}, {
  id: 27,
  elements: []
}]

var newArray = [];
for (obj of originalArray) {

    var empty = true;
    for (newobj of newArray) {
       if (obj.id == newobj.id) { empty = false; }
    }
    if (empty) {
        newArray.push({id: obj.id, elements: obj.elements});
    } else {
        for (newobj of newArray) {
           if (newobj.id == obj.id) {
               for (o of obj.elements) {
                 newobj.elements.push(o);
                }
           }
        }
    }
}
console.log(newArray);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接