【问题标题】:How can I group an array of objects by key?如何按键对一组对象进行分组?
【发布时间】:2022-01-08 05:13:21
【问题描述】:

有没有人知道一种方法(如果可能的话,lodash)通过对象键对对象数组进行分组,然后根据分组创建一个新的对象数组?例如,我有一个汽车对象数组:

const cars = [
    {
        'make': 'audi',
        'model': 'r8',
        'year': '2012'
    }, {
        'make': 'audi',
        'model': 'rs5',
        'year': '2013'
    }, {
        'make': 'ford',
        'model': 'mustang',
        'year': '2012'
    }, {
        'make': 'ford',
        'model': 'fusion',
        'year': '2015'
    }, {
        'make': 'kia',
        'model': 'optima',
        'year': '2012'
    },
];

我想创建一个按make 分组的新汽车对象数组:

const cars = {
    'audi': [
        {
            'model': 'r8',
            'year': '2012'
        }, {
            'model': 'rs5',
            'year': '2013'
        },
    ],

    'ford': [
        {
            'model': 'mustang',
            'year': '2012'
        }, {
            'model': 'fusion',
            'year': '2015'
        }
    ],

    'kia': [
        {
            'model': 'optima',
            'year': '2012'
        }
    ]
}

【问题讨论】:

  • 您的结果无效。
  • 是否有类似的方法来获取地图而不是对象?
  • 如果您使用的是 Typescript(这不是 OP 的情况),您已经拥有 groupBy 方法。您可以使用your_array.groupBy(...)
  • your_array.groupBy(...) 不存在!!

标签: javascript arrays grouping


【解决方案1】:

在纯 Javascript 中,您可以将 Array#reduce 与对象一起使用

var cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }],
    result = cars.reduce(function (r, a) {
        r[a.make] = r[a.make] || [];
        r[a.make].push(a);
        return r;
    }, Object.create(null));

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

【讨论】:

  • 如何迭代result 结果?
  • 您可以使用Object.entries 获取条目并遍历键/值对。
  • 有没有办法在分组后从数据集中删除make?它占用了额外的空间。
  • 一如既往的最佳答案。你为什么要传递 Object.create(null)?
【解决方案2】:

Timo's answer 我会这样做。简单_.groupBy,并允许分组结构中的对象有一些重复。

但是,OP 还要求删除重复的 make 键。如果你想一路走下去:

var grouped = _.mapValues(_.groupBy(cars, 'make'),
                          clist => clist.map(car => _.omit(car, 'make')));

console.log(grouped);

产量:

{ audi:
   [ { model: 'r8', year: '2012' },
     { model: 'rs5', year: '2013' } ],
  ford:
   [ { model: 'mustang', year: '2012' },
     { model: 'fusion', year: '2015' } ],
  kia: 
   [ { model: 'optima', year: '2012' } ] 
}

如果您想使用 Underscore.js 执行此操作,请注意其版本的 _.mapValues 称为 _.mapObject

【讨论】:

    【解决方案3】:

    您正在寻找_.groupBy()

    如果需要,从对象中删除您分组依据的属性应该很简单:

    const cars = [{
      'make': 'audi',
      'model': 'r8',
      'year': '2012'
    }, {
      'make': 'audi',
      'model': 'rs5',
      'year': '2013'
    }, {
      'make': 'ford',
      'model': 'mustang',
      'year': '2012'
    }, {
      'make': 'ford',
      'model': 'fusion',
      'year': '2015'
    }, {
      'make': 'kia',
      'model': 'optima',
      'year': '2012'
    }];
    
    const grouped = _.groupBy(cars, car => car.make);
    
    console.log(grouped);
    <script src='https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js'></script>

    【讨论】:

    • 如果你想让它更短,var grouped = _.groupBy(cars, 'make'); 根本不需要函数,如果访问器是一个简单的属性名称。
    • “_”代表什么?
    • @AdrianGrzywaczewski 这是名称间距“lodash”或“下划线”的默认约定。现在图书馆是模块化的,它不再需要,即。 npmjs.com/package/lodash.groupby
    • 我怎样才能对结果进行交互?
    • 我相信这将与 Object.keys(grouped)
    【解决方案4】:

    完全没有理由下载 3rd 方库来解决这个简单的问题,就像上面的解决方案所建议的那样。

    在 es6 中通过某个 key 对对象的 list 进行分组的单行版本:

    const groupByKey = (list, key) => list.reduce((hash, obj) => ({...hash, [obj[key]]:( hash[obj[key]] || [] ).concat(obj)}), {})
    

    过滤掉没有key的对象的较长版本:

    function groupByKey(array, key) {
       return array
         .reduce((hash, obj) => {
           if(obj[key] === undefined) return hash; 
           return Object.assign(hash, { [obj[key]]:( hash[obj[key]] || [] ).concat(obj)})
         }, {})
    }
    
    
    var cars = [{'make':'audi','model':'r8','year':'2012'},{'make':'audi','model':'rs5','year':'2013'},{'make':'ford','model':'mustang','year':'2012'},{'make':'ford','model':'fusion','year':'2015'},{'make':'kia','model':'optima','year':'2012'}];
    
    console.log(groupByKey(cars, 'make'))

    注意:最初的问题似乎是询问如何按品牌对汽车进行分组,但在每个组中都省略了品牌。因此,没有 3rd 方库的简短答案如下所示:

    const groupByKey = (list, key, {omitKey=false}) => list.reduce((hash, {[key]:value, ...rest}) => ({...hash, [value]:( hash[value] || [] ).concat(omitKey ? {...rest} : {[key]:value, ...rest})} ), {})
    
    var cars = [{'make':'audi','model':'r8','year':'2012'},{'make':'audi','model':'rs5','year':'2013'},{'make':'ford','model':'mustang','year':'2012'},{'make':'ford','model':'fusion','year':'2015'},{'make':'kia','model':'optima','year':'2012'}];
    
    console.log(groupByKey(cars, 'make', {omitKey:true}))

    【讨论】:

    • 这绝对不是es5
    • 它的工作原理!谁能详细说明这个reduce函数?
    • 我喜欢您的两个答案,但我看到它们都提供“make”字段作为每个“make”数组的成员。我已经根据您的答案提供了一个答案,其中交付的输出与预期的输出相匹配。谢谢!
    【解决方案5】:

    这是您自己的 groupBy 函数,它是对以下代码的概括:https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore

    function groupBy(xs, f) {
      return xs.reduce((r, v, i, a, k = f(v)) => ((r[k] || (r[k] = [])).push(v), r), {});
    }
    
    const cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }];
    
    const result = groupBy(cars, (c) => c.make);
    console.log(result);

    【讨论】:

    • 我喜欢这个答案,因为您也可以使用嵌套属性 - 非常好。我刚刚为 Typescript 更改了它,这正是我想要的 :)
    【解决方案6】:

    var cars = [{
      make: 'audi',
      model: 'r8',
      year: '2012'
    }, {
      make: 'audi',
      model: 'rs5',
      year: '2013'
    }, {
      make: 'ford',
      model: 'mustang',
      year: '2012'
    }, {
      make: 'ford',
      model: 'fusion',
      year: '2015'
    }, {
      make: 'kia',
      model: 'optima',
      year: '2012'
    }].reduce((r, car) => {
    
      const {
        model,
        year,
        make
      } = car;
    
      r[make] = [...r[make] || [], {
        model,
        year
      }];
    
      return r;
    }, {});
    
    console.log(cars);

    【讨论】:

    • 需要紧急帮助如何在上面存储,例如 [ { {"audi": [ { "model": "r8", "year": "2012" }] },{ {"ford": [ { "model": "r9", "year": "2021" }] } ...] 每个对象
    【解决方案7】:

    也可以使用简单的for 循环:

     const result = {};
    
     for(const {make, model, year} of cars) {
       if(!result[make]) result[make] = [];
       result[make].push({ model, year });
     }
    

    【讨论】:

    • 而且可能更快,更简单。我已将您的 sn-p 扩展为更具动态性,因为我不想输入 db 表中的一长串字段。另请注意,您需要将 const 替换为 let。 for ( let { TABLE_NAME, ...fields } of source) { result[TABLE_NAME] = result[TABLE_NAME] || []; result[TABLE_NAME].push({ ...fields }); }
    • 直到,谢谢! medium.com/@mautayro/…
    【解决方案8】:

    对于 JS Arrays 示例,我将 REAL GROUP BY 与此任务 here 完全相同。

    const inputArray = [ 
        { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
        { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
        { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
        { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
        { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
        { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
        { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
        { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
    ];
    
    var outObject = inputArray.reduce(function(a, e) {
      // GROUP BY estimated key (estKey), well, may be a just plain key
      // a -- Accumulator result object
      // e -- sequentally checked Element, the Element that is tested just at this itaration
    
      // new grouping name may be calculated, but must be based on real value of real field
      let estKey = (e['Phase']); 
    
      (a[estKey] ? a[estKey] : (a[estKey] = null || [])).push(e);
      return a;
    }, {});
    
    console.log(outObject);

    【讨论】:

      【解决方案9】:

      您可以尝试修改 _.groupBy 函数每次迭代调用的函数内的对象。 注意源数组改变了他的元素!

      var res = _.groupBy(cars,(car)=>{
          const makeValue=car.make;
          delete car.make;
          return makeValue;
      })
      console.log(res);
      console.log(cars);
      

      【讨论】:

      • 虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请编辑您的答案以添加解释,并说明适用的限制和假设。
      • 这对我来说似乎是最好的答案,因为您只需遍历数组一次即可获得所需的结果。无需使用其他函数来删除make 属性,而且它也更具可读性。
      【解决方案10】:

      创建一个可以重复使用的方法

      Array.prototype.groupBy = function(prop) {
            return this.reduce(function(groups, item) {
              const val = item[prop]
              groups[val] = groups[val] || []
              groups[val].push(item)
              return groups
            }, {})
          };
      

      然后你可以在下面按任何标准分组

      const groupByMake = cars.groupBy('make');
              console.log(groupByMake);
      

      var cars = [
          {
              'make': 'audi',
              'model': 'r8',
              'year': '2012'
          }, {
              'make': 'audi',
              'model': 'rs5',
              'year': '2013'
          }, {
              'make': 'ford',
              'model': 'mustang',
              'year': '2012'
          }, {
              'make': 'ford',
              'model': 'fusion',
              'year': '2015'
          }, {
              'make': 'kia',
              'model': 'optima',
              'year': '2012'
          },
      ];
        //re-usable method
      Array.prototype.groupBy = function(prop) {
      	  return this.reduce(function(groups, item) {
      		const val = item[prop]
      		groups[val] = groups[val] || []
      		groups[val].push(item)
      		return groups
      	  }, {})
      	};
        
       // initiate your groupBy. Notice the recordset Cars and the field Make....
        const groupByMake = cars.groupBy('make');
      		console.log(groupByMake);
          
          //At this point we have objects. You can use Object.keys to return an array

      【讨论】:

        【解决方案11】:

        对于 key 可以为 null 的情况,我们希望将它们分组为 others

        var cars = [{'make':'audi','model':'r8','year':'2012'},{'make':'audi','model':'rs5','year':'2013'},{'make':'ford','model':'mustang','year':'2012'},{'make':'ford','model':'fusion','year':'2015'},{'make':'kia','model':'optima','year':'2012'},
                    {'make':'kia','model':'optima','year':'2033'},
                    {'make':null,'model':'zen','year':'2012'},
                    {'make':null,'model':'blue','year':'2017'},
        
                   ];
        
        
         result = cars.reduce(function (r, a) {
                key = a.make || 'others';
                r[key] = r[key] || [];
                r[key].push(a);
                return r;
            }, Object.create(null));
        

        【讨论】:

          【解决方案12】:

          只需简单的 forEach 循环即可在此处运行,无需任何库

          var cars = [
          {
              'make': 'audi',
              'model': 'r8',
              'year': '2012'
          }, {
              'make': 'audi',
              'model': 'rs5',
              'year': '2013'
          }, {
              'make': 'ford',
              'model': 'mustang',
              'year': '2012'
          }, {
              'make': 'ford',
              'model': 'fusion',
              'year': '2015'
          }, {
              'make': 'kia',
              'model': 'optima',
              'year': '2012'
          },
          ];
          let ObjMap ={};
          
            cars.forEach(element => {
              var makeKey = element.make;
               if(!ObjMap[makeKey]) {
                 ObjMap[makeKey] = [];
               }
          
              ObjMap[makeKey].push({
                model: element.model,
                year: element.year
              });
             });
             console.log(ObjMap);

          【讨论】:

          • 最优雅易读的解决方案
          【解决方案13】:

          同意,除非您经常使用这些,否则不需要外部库。尽管有类似的解决方案可用,但如果您想了解正在发生的事情,我发现其中一些解决方案很难遵循here is a gist,该解决方案与 cmets 有一个解决方案。

          const cars = [{
            'make': 'audi',
            'model': 'r8',
            'year': '2012'
          }, {
            'make': 'audi',
            'model': 'rs5',
            'year': '2013'
          }, {
            'make': 'ford',
            'model': 'mustang',
            'year': '2012'
          }, {
            'make': 'ford',
            'model': 'fusion',
            'year': '2015'
          }, {
            'make': 'kia',
            'model': 'optima',
            'year': '2012'
          }, ];
          
          /**
           * Groups an array of objects by a key an returns an object or array grouped by provided key.
           * @param array - array to group objects by key.
           * @param key - key to group array objects by.
           * @param removeKey  - remove the key and it's value from the resulting object.
           * @param outputType - type of structure the output should be contained in.
           */
          const groupBy = (
            inputArray,
            key,
            removeKey = false,
            outputType = {},
          ) => {
            return inputArray.reduce(
              (previous, current) => {
                // Get the current value that matches the input key and remove the key value for it.
                const {
                  [key]: keyValue
                } = current;
                // remove the key if option is set
                removeKey && keyValue && delete current[key];
                // If there is already an array for the user provided key use it else default to an empty array.
                const {
                  [keyValue]: reducedValue = []
                } = previous;
          
                // Create a new object and return that merges the previous with the current object
                return Object.assign(previous, {
                  [keyValue]: reducedValue.concat(current)
                });
              },
              // Replace the object here to an array to change output object to an array
              outputType,
            );
          };
          
          console.log(groupBy(cars, 'make', true))

          【讨论】:

            【解决方案14】:

            试试这个对我来说效果很好。

            let grouped = _.groupBy(cars, 'make');

            注意:使用 lodash 库,所以包含它。

            【讨论】:

            • Uncaught ReferenceError: _ is not defined - 你应该清楚你的解决方案需要安装一个第三方库来解决这个问题。
            • 对不起,我想每个人都知道。 _ 代表并主要用于 lodash lib。所以你需要使用 lodash。请阅读问题,这样您就会知道他/她在要求 lodash。好吧,谢谢。我会记住这一点。永远不要忘记写 lib。
            • 你应该编辑你的答案以包括你正在使用一个库。
            【解决方案15】:

            原型版本也使用 ES6。 基本上,这使用reduce函数传入一个累加器和当前项,然后使用它根据传入的键构建“分组”数组。 reduce 的内部部分可能看起来很复杂,但本质上它是在测试传入对象的键是否存在,如果不存在则创建一个空数组并将当前项附加到新创建的数组,否则使用展开运算符传入当前键数组的所有对象并附加当前项。希望这对某人有帮助!。

            Array.prototype.groupBy = function(k) {
              return this.reduce((acc, item) => ((acc[item[k]] = [...(acc[item[k]] || []), item]), acc),{});
            };
            
            const projs = [
              {
                project: "A",
                timeTake: 2,
                desc: "this is a description"
              },
              {
                project: "B",
                timeTake: 4,
                desc: "this is a description"
              },
              {
                project: "A",
                timeTake: 12,
                desc: "this is a description"
              },
              {
                project: "B",
                timeTake: 45,
                desc: "this is a description"
              }
            ];
            
            console.log(projs.groupBy("project"));
            

            【讨论】:

              【解决方案16】:

              另一种解决方案:

              var cars = [
                  {'make': 'audi','model': 'r8','year': '2012'}, {'make': 'audi','model': 'rs5','year': '2013'}, 
                  {'make': 'ford','model': 'mustang','year': '2012'}, {'make': 'ford','model': 'fusion','year': '2015'}, 
                  {'make': 'kia','model': 'optima','year': '2012'},
              ];
              
              
              const reducedCars = cars.reduce((acc, { make, model, year }) => (
                  { 
                    ...acc, 
                    [make]: acc[make] ? [ ...acc[make], { model, year }] : [ { model, year } ],
                  }
               ), {});
              
              console.log(reducedCars);

              【讨论】:

                【解决方案17】:

                你也可以像这样使用array#forEach()方法:

                const cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }];
                
                let newcars = {}
                
                cars.forEach(car => {
                  newcars[car.make] ? // check if that array exists or not in newcars object
                    newcars[car.make].push({model: car.model, year: car.year})  // just push
                   : (newcars[car.make] = [], newcars[car.make].push({model: car.model, year: car.year})) // create a new array and push
                })
                
                console.log(newcars);

                【讨论】:

                  【解决方案18】:
                  function groupBy(data, property) {
                    return data.reduce((acc, obj) => {
                      const key = obj[property];
                      if (!acc[key]) {
                        acc[key] = [];
                      }
                      acc[key].push(obj);
                      return acc;
                    }, {});
                  }
                  groupBy(people, 'age');
                  

                  【讨论】:

                    【解决方案19】:

                    我喜欢写它,没有依赖/复杂性,只是纯粹的简单 js。

                    const mp = {}
                    const cars = [
                      {
                        model: 'Imaginary space craft SpaceX model',
                        year: '2025'
                      },
                      {
                        make: 'audi',
                        model: 'r8',
                        year: '2012'
                      },
                      {
                        make: 'audi',
                        model: 'rs5',
                        year: '2013'
                      },
                      {
                        make: 'ford',
                        model: 'mustang',
                        year: '2012'
                      },
                      {
                        make: 'ford',
                        model: 'fusion',
                        year: '2015'
                      },
                      {
                        make: 'kia',
                        model: 'optima',
                        year: '2012'
                      }
                    ]
                    
                    cars.forEach(c => {
                      if (!c.make) return // exit (maybe add them to a "no_make" category)
                    
                      if (!mp[c.make]) mp[c.make] = [{ model: c.model, year: c.year }]
                      else mp[c.make].push({ model: c.model, year: c.year })
                    })
                    
                    console.log(mp)

                    【讨论】:

                      【解决方案20】:

                      我喜欢@metakunfu 的回答,但它并没有完全提供预期的输出。 这是一个在最终 JSON 有效负载中摆脱“make”的更新。

                      var cars = [
                          {
                              'make': 'audi',
                              'model': 'r8',
                              'year': '2012'
                          }, {
                              'make': 'audi',
                              'model': 'rs5',
                              'year': '2013'
                          }, {
                              'make': 'ford',
                              'model': 'mustang',
                              'year': '2012'
                          }, {
                              'make': 'ford',
                              'model': 'fusion',
                              'year': '2015'
                          }, {
                              'make': 'kia',
                              'model': 'optima',
                              'year': '2012'
                          },
                      ];
                      
                      result = cars.reduce((h, car) => Object.assign(h, { [car.make]:( h[car.make] || [] ).concat({model: car.model, year: car.year}) }), {})
                      
                      console.log(JSON.stringify(result));
                      

                      输出:

                      {  
                         "audi":[  
                            {  
                               "model":"r8",
                               "year":"2012"
                            },
                            {  
                               "model":"rs5",
                               "year":"2013"
                            }
                         ],
                         "ford":[  
                            {  
                               "model":"mustang",
                               "year":"2012"
                            },
                            {  
                               "model":"fusion",
                               "year":"2015"
                            }
                         ],
                         "kia":[  
                            {  
                               "model":"optima",
                               "year":"2012"
                            }
                         ]
                      }
                      

                      【讨论】:

                        【解决方案21】:

                        使用 lodash/fp,您可以使用 _.flow() 创建一个函数,该函数首先按一个键分组,然后映射每个组,并从每个项目中省略一个键:

                        const { flow, groupBy, mapValues, map, omit } = _;
                        
                        const groupAndOmitBy = key => flow(
                          groupBy(key),
                          mapValues(map(omit(key)))
                        );
                        
                        const cars = [{ make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' }];
                        
                        const groupAndOmitMake = groupAndOmitBy('make');
                        
                        const result = groupAndOmitMake(cars);
                        
                        console.log(result);
                        .as-console-wrapper { max-height: 100% !important; top: 0; }
                        <script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

                        【讨论】:

                          【解决方案22】:

                          打字稿中的对象分组数组:

                          groupBy (list: any[], key: string): Map<string, Array<any>> {
                              let map = new Map();
                              list.map(val=> {
                                  if(!map.has(val[key])){
                                      map.set(val[key],list.filter(data => data[key] == val[key]));
                                  }
                              });
                              return map;
                          });
                          

                          【讨论】:

                          • 当您搜索每个键时,这看起来效率很低。搜索的复杂度很可能是 O(n)。
                          • 使用 Typescript 你已经有了 groupBy 方法。您可以使用your_array.groupBy(...)
                          【解决方案23】:

                          我做了一个基准测试来测试每个不使用外部库的解决方案的性能。

                          JSBen.ch

                          @Nina Scholz 发布的reduce() 选项似乎是最佳选项。

                          【讨论】:

                            【解决方案24】:

                            添加了Array.prototype.groupByArray.prototype.groupByToMapA proposal 现在处于第3 阶段!

                            当它达到第 4 阶段并在大多数主流浏览器上实现时,您将能够做到这一点:

                            const cars = [
                              { make: 'audi', model: 'r8', year: '2012' },
                              { make: 'audi', model: 'rs5', year: '2013' },
                              { make: 'ford', model: 'mustang', year: '2012' },
                              { make: 'ford', model: 'fusion', year: '2015' },
                              { make: 'kia', model: 'optima', year: '2012' }
                            ];
                            
                            const grouped = cars.groupBy(item => item.make);
                            console.log(grouped);
                            

                            这将输出:

                            {
                              audi: [
                                { make: 'audi', model: 'r8', year: '2012' },
                                { make: 'audi', model: 'rs5', year: '2013' }
                              ],
                              ford: [
                                { make: 'ford', model: 'mustang', year: '2012' },
                                { make: 'ford', model: 'fusion', year: '2015' }
                              ],
                              kia: [
                                { make: 'kia', model: 'optima', year: '2012' }
                              ]
                            }
                            

                            在那之前,你可以使用this core-js polyfill:

                            const cars = [
                              { make: 'audi', model: 'r8', year: '2012' },
                              { make: 'audi', model: 'rs5', year: '2013' },
                              { make: 'ford', model: 'mustang', year: '2012' },
                              { make: 'ford', model: 'fusion', year: '2015' },
                              { make: 'kia', model: 'optima', year: '2012' }
                            ];
                            
                            const grouped = cars.groupBy(item => item.make);
                            //console.log(grouped);
                            
                            // Optional: remove the "make" property from resulting object
                            const entriesUpdated = Object
                              .entries(grouped)
                              .map(([key, value]) => [
                                key,
                                value.map(({make, ...rest}) => rest)
                              ]);
                            const noMake = Object.fromEntries(entriesUpdated);
                            console.log(noMake);
                            &lt;script src="https://unpkg.com/core-js-bundle@3.20.1/minified.js"&gt;&lt;/script&gt;

                            【讨论】:

                              【解决方案25】:

                              如果您不想输入所有字段,请在 @Jonas_Wilms 的 answer 上构建:

                                  var result = {};
                              
                                  for ( let { first_field, ...fields } of your_data ) 
                                  { 
                                     result[first_field] = result[first_field] || [];
                                     result[first_field].push({ ...fields }); 
                                  }
                              
                              

                              我没有做任何基准测试,但我相信使用 for 循环也会比 this answer 中建议的任何方法更有效。

                              【讨论】:

                              • for...of 循环效率最低。为 forEach 循环使用 for(i...)
                              【解决方案26】:
                              const reGroup = (list, key) => {
                                  const newGroup = {};
                                  list.forEach(item => {
                                      const newItem = Object.assign({}, item);
                                      delete newItem[key];
                                      newGroup[item[key]] = newGroup[item[key]] || [];
                                      newGroup[item[key]].push(newItem);
                                  });
                                  return newGroup;
                              };
                              
                              const animals = [
                                {
                                  type: 'dog',
                                  breed: 'puddle'
                                },
                                {
                                  type: 'dog',
                                  breed: 'labradoodle'
                                },
                                {
                                  type: 'cat',
                                  breed: 'siamese'
                                },
                                {
                                  type: 'dog',
                                  breed: 'french bulldog'
                                },
                                {
                                  type: 'cat',
                                  breed: 'mud'
                                }
                              ];
                              console.log(reGroup(animals, 'type'));
                              
                              const cars = [
                                {
                                    'make': 'audi',
                                    'model': 'r8',
                                    'year': '2012'
                                }, {
                                    'make': 'audi',
                                    'model': 'rs5',
                                    'year': '2013'
                                }, {
                                    'make': 'ford',
                                    'model': 'mustang',
                                    'year': '2012'
                                }, {
                                    'make': 'ford',
                                    'model': 'fusion',
                                    'year': '2015'
                                }, {
                                    'make': 'kia',
                                    'model': 'optima',
                                    'year': '2012'
                                },
                              ];
                              
                              console.log(reGroup(cars, 'make'));
                              

                              【讨论】:

                                【解决方案27】:

                                这是一个受 Java 中的 Collectors.groupingBy() 启发的解决方案:

                                function groupingBy(list, keyMapper) {
                                  return list.reduce((accummalatorMap, currentValue) => {
                                    const key = keyMapper(currentValue);
                                    if(!accummalatorMap.has(key)) {
                                      accummalatorMap.set(key, [currentValue]);
                                    } else {
                                      accummalatorMap.set(key, accummalatorMap.get(key).push(currentValue));
                                    }
                                    return accummalatorMap;
                                  }, new Map());
                                }

                                这将给出一个 Map 对象。

                                // Usage
                                
                                const carMakers = groupingBy(cars, car => car.make);

                                【讨论】:

                                  【解决方案28】:

                                  这是另一个解决方案。根据要求。

                                  我想创建一个按 make 分组的新汽车对象数组:

                                  function groupBy() {
                                    const key = 'make';
                                    return cars.reduce((acc, x) => ({
                                      ...acc,
                                      [x[key]]: (!acc[x[key]]) ? [{
                                        model: x.model,
                                        year: x.year
                                      }] : [...acc[x[key]], {
                                        model: x.model,
                                        year: x.year
                                      }]
                                    }), {})
                                  }
                                  

                                  输出:

                                  console.log('Grouped by make key:',groupBy())
                                  

                                  【讨论】:

                                    猜你喜欢
                                    相关资源
                                    最近更新 更多