0

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

2

5 Answers 5

2

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)

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, this is great. I'm realizing that I cannot use Object.entries. Are you able to add a solution without it?
0

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

Comments

0

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

Comments

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

2 Comments

What if there is an object in the array that look like { foo: ["f", "b"], bar: ["z"], zoo: ["123"] }
@ibrahimmahrir, updated my answer with a check of Object.hasOwnProperty
0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.