【问题标题】:How can you merge objects in array of objects?如何合并对象数组中的对象?
【发布时间】:2019-03-16 14:29:49
【问题描述】:

我正在寻找将所有对象合并到一个数组中的最佳解决方案

const arrayOfObjects = [
 {name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
];

我要实现:{name: ['Fred', 'Anne'], surname: ['Example', 'Shultz']}

最好的选择是什么(es6)?也许我可以使用 lodash 做类似的事情?我应该使用哪些助手?

【问题讨论】:

  • arrayOfObjects 中的每个对象都保证具有相同的属性吗?
  • @Rafonix 你应该接受最佳答案。

标签: javascript arrays ecmascript-6 lodash


【解决方案1】:

以下应该可以工作 - 使用一些 ES6 助手,但关键是 ES5 中的 Array#reduce

const result = arrayOfObjects.reduce((acc, obj) => {
    for (let key in obj) {
        if (key in acc) {
            acc[key].push(obj[key]);
        }
        else {
            acc[key] = [obj[key]];
        }
    }
    return acc;
}, {});

【讨论】:

    【解决方案2】:

    轻松使用 lodash:

    grouped = _.mapValues(arrayOfObjects[0], 
        (val, key) => _.map(arrayOfObjects, key))
    

    纯 es6

    let grouped = {};
    
    for (let obj of arrayOfObjects)
        for (let [key, val] of Object.entries(obj))
            grouped[key] = (grouped[key] || []).concat(val)
    

    如果每个项目的密钥不同,您可以使用类似的方法来收集它们:

    grouped = _(arrayOfObjects)
        .flatMap(_.entries)
        .groupBy(0)
        .mapValues(x => _.map(x, 1))
        .value()
    

    【讨论】:

    • 我喜欢 lodash 方法,但它不够通用。如果超过第一个对象的任何对象具有不同的属性,它将中断。例如{name: 'John', city: 'Miami'}
    • jsfiddle.net/akrion/tp70frm5/627。您将在控制台中看到,首先您有一个undefined 作为surname 中的最后一个元素,其次您没有city 的属性,因为您在第一个对象上而不是every 上做了mapValues数组。
    • @Akrion:是的,我明白了,已修复!
    • @georg 是不是固定的 lodash 版本和我的答案一模一样?
    【解决方案3】:

    你可以这样做:

    const arrayOfObjects = [
      {name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
    ];
    
    const result = {};
    arrayOfObjects.forEach(item => {
      Object.keys(item).forEach(key => {
        if (!result[key]) {
          result[key] = [];
        }
        result[key].push(item[key]);
      });
    });
    
    console.log(result);

    【讨论】:

      【解决方案4】:

      您可以通过迭代条目并收集值来减少数组,具体取决于键。

      const
          array = [{ name: 'Fred', surname: 'Shultz' }, { name: 'Anne', surname: 'Example' }],
          result = array.reduce((r, o) => {
              Object.entries(o).forEach(([k, v]) => (r[k] = r[k] || []).push(v));
              return r;
          }, Object.create(null));
      
      console.log(result);

      【讨论】:

        【解决方案5】:

        这是一个lodash方法

          _(input).flatMap(_.entries).groupBy(0).mapValues(v => _.map(v, 1)).value()
        

        var input = [
         {name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
        ];
        
        var res =   _(input).flatMap(_.entries).groupBy(0).mapValues(v => _.map(v, 1)).value()
        
        console.log(res);
        <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

        如果对象没有完全相同的键集,这将引起注意

        【讨论】:

        • 这导致输出结构与预期略有不同。
        • @ssc-hrep3 查看编辑,我忘记将其映射到预期的结果类型
        【解决方案6】:

        你可以像这样使用 lodash 的mergeWith

        const result = _.mergeWith({}, ...arrayOfObjects, (value, objValue) =>
            (value || []).concat(objValue)
        );
        

        示例:

        const arrayOfObjects = [
            {name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
        ];
        
        const result = _.mergeWith({}, ...arrayOfObjects, (value, objValue) =>
            (value || []).concat(objValue)
        );
        
        console.log(result);
        <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

        【讨论】:

          【解决方案7】:

          数组reduce的捷径:

          const arrayOfObjects = [
           {name: "name1", surname: "surname1"}, {name: 'Anne', surname: 'Example'}, {name: 'name3', surname: 'Example3'}
          ];
          /*
          {name: ['Fred', 'Anne'], surname: ['Example', 'Shultz']}
          */
          var result = arrayOfObjects.reduce((obj,current)=>{
              (obj['name'] = obj['name']||[]).push(current.name);
              (obj['surname'] = obj['surname']||[]).push(current.surname);
              return obj;
          },{});
          console.log(result);

          【讨论】:

            【解决方案8】:

            如果arrayOfObjects 设置在这两个道具上,那么它很简单:

            const data = [{ name: 'Fred', surname: 'Shultz' }, { name: 'Anne', surname: 'Example' }]
            
            const r = data.reduce((r,c) => 
               (r.name.push(c.name), r.surname.push(c.surname),r), {name:[], surname:[]})
            
            console.log(r)

            一个reduce 和一个{name:[], surname:[]} 的累加器将被填充。

            如果您需要更通用并为any set of objects工作:

            const data = [{
              name: 'Fred',
              surname: 'Shultz'
            },{
              name: 'Anne',
              surname: 'Example'	
            },{
              name: 'John',
              position: 'Dev' // <--- Notice different prop
            }]
            
            const result = data.reduce((r,c) => 
              (Object.keys(c).map(k => r[k] = [...r[k] || [], c[k]]), r), {})
            
            console.log(result)

            再次只是一个reduceObject.keys 来完成这项工作。

            请注意,这两种方法都使用 ES6 arrow functionsarray destricturing 并且(对于第二种方法)通过将多个操作括在括号中来组合多个操作 (op1,op2)

            【讨论】:

              【解决方案9】:

              不要让它变得过于复杂:

              const arrayOfObjects = [
                  {name: 'Fred', surname: 'Shultz'},
                  {name: 'Anne', surname: 'Example'}
              ];
              
              const result = {name:[], surname:[]};
              for (const obj of arrayOfObjects)
                  for (const prop in result)
                      result[prop].push(obj[prop]);
              

              我会假设您静态知道结果应该具有的属性名称 - 无论如何都不能真正动态地做到这一点,因为这对于空输入数组无法正常工作。

              【讨论】:

              • 你不能在对象上使用 for..of,你应该使用 for..in 代替,或者遍历Object.keys(result)
              • @Frax 哎呀,这就是我的意思。
              【解决方案10】:

              这是一个实现细节的摘要,以相当容易理解和可读的方式编写。

              https://codesandbox.io/s/r7x16j950n

              const arrayOfObjects = [
                { name: "Fred", surname: "Shultz" },
                { name: "Anne", surname: "Example" }
              ];
              
              let obj = {};
              
              arrayOfObjects.forEach(row => {
                Object.keys(row).forEach(key => {
                  obj[key] = !obj[key]
                    ? [row[key]]
                    : [...obj[key], row[key]];
                });
              });
              
              console.log(obj);
              

              【讨论】:

                【解决方案11】:

                没有任何库

                const mergeObjectInArray=(input)=>{
                const myObj={};
                Object.keys(input[0]).forEach(key=>myObj[key]=input.map(inp=>inp[key]));
                return myObj;
                }
                

                【讨论】:

                  【解决方案12】:

                  javascript

                  var myInput = [{ a: 1, b: 2, c: 3 }, { a: 2, b: 4, c: 6 }, { a: 7, b: 8, c: 9 }];
                      var myArray = [];
                      var myObject = {};
                      function isArray(a){
                          return Object.prototype.toString.call(a) === '[object Array]' ;
                      }
                      for (var i = 0; i < myInput.length; i++) {
                          for (var key in myInput[i]) {
                              if (myInput[i].hasOwnProperty(key)) {
                                  if (myArray.indexOf(key) === -1) {
                                      myArray.push(key);
                                      myObject[key] = myInput[i][key];
                                  } else {
                                      if (myObject.hasOwnProperty(key)) {
                                          newary = [];
                                          if (isArray(myObject[key])) {
                                              for (var i = 0; i < myObject[key].length; i++) {
                                                  newary.push(myObject[key][i]);
                                              }
                                          } else {
                                              newary.push(myObject[key]);
                                          }
                                          newary.push(myInput[i][key]);
                                          myObject[key] = newary;
                                      }
                                  }
                              }
                          }
                      }
                      console.log(myObject);

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-07-22
                    • 2020-07-11
                    • 1970-01-01
                    • 2019-07-23
                    相关资源
                    最近更新 更多