【问题标题】:Merge objects with same id in array合并数组中具有相同id的对象
【发布时间】:2019-11-04 11:22:43
【问题描述】:

我想我有一个非常简单的问题,但仍然没有找到解决方案。我有一个如下所示的数组:

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: []
}]

我已经多次尝试,但仍然没有找到一种优雅的方式。

【问题讨论】:

  • 嗨!请使用tour(您将获得徽章!)并通读help center,尤其是How do I ask a good question? 您最好的选择是进行研究,search 以获取有关 SO 的相关主题,然后试一试. 如果您在进行更多研究和搜索后遇到困难并且无法摆脱困境,请发布您的尝试minimal reproducible example,并具体说明您遇到的问题。人们会很乐意提供帮助。
  • 所以通过查看下面的解决方案,它并不死简单;)

标签: javascript ecmascript-6


【解决方案1】:

您可以创建一个以 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 中使用 ...
  • 如果传递多个项目,推送中的... 是必需的,或者您可以使用concat(item.elements),但需要为其分配元素,因为它返回一个新数组。 ...item 只是“打破”原始数组的常见做法,因此对对象的(浅)修改不会改变原始数组 - 通常这种不可变编码风格会导致更少的意外副作用,并且还可以进行对象相等比较更高效、更容易,例如reactjs.org/docs/react-api.html#reactpurecomponent 是由它实现的
【解决方案2】:

您可以使用Array.prototype.reduce() 创建一个对象,其中ids 作为属性,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; }

【讨论】:

    【解决方案3】:

    你可以使用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;
    }, [])
    

    【讨论】:

      【解决方案4】:

      试试这个代码:

      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: []
      }]
      

      【讨论】:

        【解决方案5】:

        这将起作用并且也很容易理解。 首先,我们检查 id 是否已经在 newArray 中,并且我们通过循环外的布尔值来保存它,我们可以稍后验证。 在此之后,如果 id "space" 为空,我们将填充它,如果不是,则那里已经有一个 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: []
        }]
        
        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);

        【讨论】:

          【解决方案6】:

          您可以使用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])

          【讨论】:

            【解决方案7】:

            您可以使用嵌套的 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);

            【讨论】:

              猜你喜欢
              • 2019-08-02
              • 2014-10-08
              • 1970-01-01
              • 1970-01-01
              • 2020-02-08
              • 2019-06-05
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多