How can you merge objects in array of objects?

2020-02-07 00:19发布

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?

12条回答
爷、活的狠高调
2楼-- · 2020-02-07 00:26

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()
查看更多
成全新的幸福
3楼-- · 2020-02-07 00:28

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;
}, {});
查看更多
干净又极端
4楼-- · 2020-02-07 00:30

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)

查看更多
姐就是有狂的资本
5楼-- · 2020-02-07 00:31

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);

查看更多
爷的心禁止访问
6楼-- · 2020-02-07 00:33

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);
查看更多
家丑人穷心不美
7楼-- · 2020-02-07 00:36

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>

查看更多
登录 后发表回答