可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm looking for the best solution to merge all objects in one array
const arrayOfObjects = [
{name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
];
I want to achieve: {name: ['Fred', 'Anne'], surname: ['Example', 'Shultz']}
What's the best option for that (es6)? Maybe I can do something like that using lodash? Which helpers should I use?
回答1:
You can use lodash's mergeWith
like so:
const result = _.mergeWith({}, ...arrayOfObjects, (value, objValue) =>
(value || []).concat(objValue)
);
Example:
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>
回答2:
You could reduce the array by iterating the entries and collecting the values, depending of the keys.
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);
回答3:
You could do it like this:
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:
easy with lodash:
grouped = _.mapValues(arrayOfObjects[0],
(val, key) => _.map(arrayOfObjects, key))
pure es6
let grouped = {};
for (let obj of arrayOfObjects)
for (let [key, val] of Object.entries(obj))
grouped[key] = (grouped[key] || []).concat(val)
if the keys differ from item to item, you could use something like this to collect them all:
grouped = _(arrayOfObjects)
.flatMap(_.entries)
.groupBy(0)
.mapValues(x => _.map(x, 1))
.value()
回答5:
Short way with array 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);
回答6:
Don't make it any more complicated than it needs to be:
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]);
I will assume that you statically know the property names that your result should have - one can't really do it dynamically anyway as that wouldn't work properly for an empty input array.
回答7:
Here is a lodash approach
_(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>
This will take care if the objects doesn't have exactly same key sets
回答8:
If the arrayOfObjects
is set on these 2 props then it is as simple as:
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)
One reduce
with an accumulator of {name:[], surname:[]}
to be filled.
If you need to be more generic and work for 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)
Again is just a reduce
with Object.keys
to do the job.
Note both approaches utilize ES6 arrow functions, array destricturing and (for the 2nd one) combining multiple operations via enclosing them in parentheses (op1,op2)
回答9:
The following should work - uses a few ES6 helpers, but the key is Array#reduce
which is in ES5.
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;
}, {});
回答10:
This is one abroach of implementation details, written in fairly easy to understand and readable manner.
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:
Without any library
const mergeObjectInArray=(input)=>{
const myObj={};
Object.keys(input[0]).forEach(key=>myObj[key]=input.map(inp=>inp[key]));
return myObj;
}
回答12:
with pure 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);