简体   繁体   中英

Transform an array of objects into a single object

I am trying to combine an array of object into one object that merges the values of all of the like properties.

 objArray = [{ foo: ["f", "b"], bar: ["e"] }, { foo: ["a", "c"], bar: ["a", "c"] }, { foo: ["f", "b"], bar: ["z"] }]; const newObj = { foo: [], bar: [] }; objArray.forEach((obj) => { newObj.foo.push(...obj.foo); newObj.bar.push(...obj.bar); }); console.log(newObj); 

I am getting the desired output with the above code. Is using a forEach loop like above the best way to achieve what I am setting out to do? Ideally I don't want to have to specify the properties to merge, I would like the code to merge identical property names automatically.

Edit:

I need to support IE11

Can use a nested reduce() of Object#entries() to iterate properties without needing to hard code specific property names anywhere

 objArray = [{ foo: ["f", "b"], bar: ["e"] }, { foo: ["a", "c"], bar: ["a", "c"] }, { foo: ["f", "b"], bar: ["z"] }]; const res= objArray.reduce((acc,c)=>{ return Object.entries(c).reduce((a,[k,v])=>{ a[k] = (a[k] || []).concat(v) return a },acc) },{}) console.log(res) 

You could take the entries of the objects for an arbitrary count of keys and values.

 var data = [{ foo: ["f", "b"], bar: ["e"] }, { foo: ["a", "c"], bar: ["a", "c"] }, { foo: ["f", "b"], bar: ["z"] }], merged = data.reduce((r, o) => Object.entries(o).reduce((s, [k, v]) => Object.assign(s, { [k]: (s[k] || []).concat(v) }), r), {}); console.log(merged); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

To achieve expected result, use Object.keys and two loops using forEach

  1. First loop with forEach will handle each object
  2. Second loop with Object.keys will handle each object keys and push to new Array with keys
  3. Use Object.hasOwnProperty to key value in newObj with original array object properties

 objArray = [ { foo: ["f", "b"], bar: ["e"], zoo: ["z"] }, { foo: ["a", "c"], bar: ["a", "c"] }, { foo: ["f", "b"], bar: ["z"] } ]; const newObj = { foo: [], bar: [] }; objArray.forEach(obj => { Object.keys(obj).forEach(v => { if (newObj.hasOwnProperty(v)) { newObj[v].push(obj[v]); } }); }); console.log(newObj); 

codepen for reference - https://codepen.io/nagasai/pen/MqOpWm?editors=1010

Using forEach as you, but for in inside.

 var objArray = [{foo: ["f", "b"],bar: ["e"]},{foo: ["a", "c"],bar:["a", "c"]},{foo: ["f", "b"],bar: ["z"]}]; var newObj = {}; objArray.forEach(o => { for (p in o) { if (!(p in newObj)) { newObj[p] = []; } newObj[p] = [...newObj[p], ...o[p]]; } }); console.log(newObj); 

Taking @charlietfl answer and editing it for IE (using Object.keys instead of Object.entries )

 objArray = [{ foo: ["f", "b"], bar: ["e"] }, { foo: ["a", "c"], bar: ["a", "c"] }, { foo: ["f", "b"], bar: ["z"] }]; const res = objArray.reduce((acc, c) => { return Object.keys(c).reduce((a, k) => { let v = c[k]; a[k] = (a[k] || []).concat(v); return a; }, acc); }, {}); console.log(res) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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