简体   繁体   English

从对象数组中按键创建对象数组

[英]Create array of objects by key from array of objects

There are a lot of questions like this on here, but I couldn't find one that matched my needs. 这里有很多这样的问题,但我找不到符合我需求的问题。 I'm looking for a relatively simple solution on how to stack objects in an array into new arrays based on a key. 我正在寻找一个相对简单的解决方案,关于如何根据键将数组中的对象堆叠到新数组中。

In the example data we're grouping the objects by their "ship" key. 在示例数据中,我们通过“船”键对对象进行分组。

Original data: 原始数据:

 var myObjArray = [
    {
        name:'Malcolm Reynolds',
        ship:'Serenity'
    },
    {
        name: 'Carmen Ibanez',
        ship: 'Rodger Young',
    },
    {
        name: 'Zander Barcalow',
        ship: 'Rodger Young',
    },
    {
        name:'Hoban Washburne',
        ship:'Serenity'
    },
    {
        name:'James Kirk',
        ship:'USS Enterprise'
    }
];

Restructured Data: 重组数据:

    var myNewObjArray = [
    [{
        name:'Malcolm Reynolds',
        ship:'Serenity'
    },
    {
        name:'Hoban Washburne',
        ship:'Serenity'
    }],
    [{
        name: 'Carmen Ibanez',
        ship: 'Rodger Young',
    },
    {
        name: 'Zander Barcalow',
        ship: 'Rodger Young',
    }],
    {
        name:'James Kirk', // optionally also stick in an array
        ship:'USS Enterprise'
    }
];

If anyone has a solution for this I'd appreciate it, my current attempt is sloppy to say the least. 如果有人有解决方案,我会很感激,我目前的尝试至少可以说是草率的。

You could take an object for and the ship value as key for the same group. 您可以将对象和ship值作为同一组的关键。 For the result take only the values of the object. 对于结果,只取对象的值。

 var data = [{ name: 'Malcolm Reynolds', ship: 'Serenity' }, { name: 'Carmen Ibanez', ship: 'Rodger Young' }, { name: 'Zander Barcalow', ship: 'Rodger Young' }, { name: 'Hoban Washburne', ship: 'Serenity' }, { name: 'James Kirk', ship: 'USS Enterprise' }], grouped = Object.values(data.reduce((r, o) => { if (!r[o.ship]) { r[o.ship] = o; return r; } if (!Array.isArray(r[o.ship])) r[o.ship] = [r[o.ship]]; r[o.ship].push(o); return r; }, {})); console.log(grouped); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

An approach with a Map 一种使用Map的方法

 var data = [{ name: 'Malcolm Reynolds', ship: 'Serenity' }, { name: 'Carmen Ibanez', ship: 'Rodger Young' }, { name: 'Zander Barcalow', ship: 'Rodger Young' }, { name: 'Hoban Washburne', ship: 'Serenity' }, { name: 'James Kirk', ship: 'USS Enterprise' }], grouped = Array.from( data .reduce((m, o) => m.set(o.ship, [...(m.get(o.ship) || []), o]), new Map) .values(), a => a.length === 1 ? a[0] : a ); console.log(grouped); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Find and deduplicate names of ships, then find personnel for every ship. 找到并重复删除船舶名称,然后找到每艘船的人员。

 const myObjArray = [ { name:'Malcolm Reynolds', ship:'Serenity' }, { name: 'Carmen Ibanez', ship: 'Rodger Young', }, { name: 'Zander Barcalow', ship: 'Rodger Young', }, { name:'Hoban Washburne', ship:'Serenity' }, { name:'James Kirk', ship:'USS Enterprise' } ]; const ships = myObjArray.map(({ship}) => ship).filter((ship, i, arr) => arr.indexOf(ship) === i); const personnelArray = ships.map(ship => myObjArray.filter(entry => entry.ship === ship)); console.log(personnelArray); 

Another clean and elegant solution would be working with Lodash . 另一个干净而优雅的解决方案是与Lodash合作

First, group by the array with the relevant key.Then,Get the values from the object. 首先,使用相关键对数组进行分组。然后,从对象中获取值。

From the docs : 来自文档:

Creates an object composed of keys generated from the results of running each element of collection thru iteratee. 创建一个对象,该对象由通过iteratee运行集合的每个元素的结果生成的键组成。 The order of grouped values is determined by the order they occur in collection. 分组值的顺序由它们在集合中出现的顺序确定。 The corresponding value of each key is an array of elements responsible for generating the key. 每个键的对应值是负责生成密钥的元素数组。 The iteratee is invoked with one argument: (value). 使用一个参数调用iteratee :( value)。

 const myObjArray = [ { name:'Malcolm Reynolds', ship:'Serenity' }, { name: 'Carmen Ibanez', ship: 'Rodger Young', }, { name: 'Zander Barcalow', ship: 'Rodger Young', }, { name:'Hoban Washburne', ship:'Serenity' }, { name:'James Kirk', ship:'USS Enterprise' } ]; var result =_.values((_.groupBy(myObjArray , 'ship'))); console.log(result); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script> 

Probably not the most performant but this should work. 可能不是最高效的,但这应该有效。

var tempObj = {};
myObjArray.forEach((item)=>{
  var ship = item.ship;
  if (!tempObj.hasOwnProperty(ship)) {
    tempObj[ship] = []; //create the key in the key in the obj and init to an empty array
  }
  tempObj[ship].push(item); //add the item to the array
});

var myNewObjArray = [];

for (key in tempObj) {
  myNewObjArray.push([]); //add a new array for each key in the tempObj
  tempObj[key].forEach((item)=>{ //iterate over the array of items in the tempObj for that key
    myNewObjArray[myNewObjArray.length-1].push(item); //add the item to the last array in the object which should have been created.
  });
}

Not sure how you plan on using the data but would a more concise data structure look something like an object where the ship has staff rather than an array of arrays where the ship name is continually repeated in a redundant way? 不确定你打算如何使用数据,但是更简洁的数据结构看起来就像船上有员工的对象,而不是一个数组,其中船名以冗余的方式不断重复? What about this data structure? 这个数据结构怎么样?

 var myObjArray = [ { name:'Malcolm Reynolds', ship:'Serenity' }, { name: 'Carmen Ibanez', ship: 'Rodger Young', }, { name: 'Zander Barcalow', ship: 'Rodger Young', }, { name:'Hoban Washburne', ship:'Serenity' }, { name:'James Kirk', ship:'USS Enterprise' } ]; const staffShips = data => data.reduce((ships, item) => { const ship = ships[item.ship]; if (ship) { ship.push(item.name); } else { ships[item.ship] = [ item.name ]; } return ships; }, {}); console.log(staffShips(myObjArray)); 

This is slightly different in that it's an object with keys, but that those keys contain arrays with the data how you want to see it. 这略有不同,因为它是一个带键的对象,但这些键包含数组,其中包含您希望如何看到它的数据。

var newObject = {};

for (var i in myObjArray) {
     var newKey = myObjArray[i].ship.replace(/\s+/g, '');
   if (typeof(newObject[newKey]) == "undefined") newObject[newKey] = [];
   newObject[newKey].push({
        name: myObjArray[i].name, ship: myObjArray[i].ship
   });
}

Here you have another approach, first, we use Array.reduce() to generate an object that will group elements by the ship property. 这里有另一种方法,首先,我们使用Array.reduce()生成一个对象,该对象将按ship属性对元素进行分组。 Then we use Array.map() over the generated Object.values() to drop the array if only holds one element. 然后我们在生成的Object.values()上使用Array.map()来删除数组(如果只保存一个元素)。 The map could be optional if you don't really need this last step. 如果您真的不需要最后一步,那么地图可以是可选的。

 var myObjArray = [ {name:'Malcolm Reynolds', ship:'Serenity'}, {name: 'Carmen Ibanez', ship: 'Rodger Young'}, {name: 'Zander Barcalow', ship: 'Rodger Young'}, {name:'Hoban Washburne', ship:'Serenity'}, {name:'James Kirk', ship:'USS Enterprise'} ]; let res = myObjArray.reduce((acc, obj) => { acc[obj.ship] = acc[obj.ship] || []; acc[obj.ship].push(obj); return acc; }, {}); res = Object.values(res).map(arr => (arr.length <= 1 ? arr[0] : arr)); console.log(res); 
 .as-console {background-color:black !important; color:lime;} .as-console-wrapper {max-height:100% !important; top:0;} 

In Javascript, to group objects by property, Array.prototype.reduce() method can be used to consolidate the input array data into a set of results, grouped by a key( in this case 'ship'). 在Javascript中,要按属性对对象进行分组,可以使用Array.prototype.reduce()方法将输入数组数据合并为一组结果,按键分组(在本例中为“ship”)。 Use Object.values to extract the values from the resulting set by dropping the keys 使用Object.values通过删除键从结果集中提取值

 var data = [ { name: 'Malcolm Reynolds', ship: 'Serenity' }, { name: 'Carmen Ibanez', ship: 'Rodger Young' }, { name: 'Zander Barcalow', ship: 'Rodger Young' }, { name: 'Hoban Washburne', ship: 'Serenity' }, { name: 'James Kirk', ship: 'USS Enterprise' }]; var myNewObjArray = data.reduce((res,obj) =>{ const key = obj.ship; if(!res[key]){ res[key] = []; } res[key].push(obj) return res; }, {}); console.log(Object.values(myNewObjArray)); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM