Estoy tratando de combinar una matriz de objetos en un objeto que combina los valores de todas las propiedades similares.

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

Estoy obteniendo el resultado deseado con el código anterior. ¿Usar un bucle forEach como el anterior es la mejor manera de lograr lo que me propongo hacer? Idealmente, no quiero tener que especificar las propiedades para fusionar, me gustaría que el código combine automáticamente nombres de propiedad idénticos.

Editar:

Necesito soportar IE11

0
Mcestone 7 sep. 2018 a las 17:11

5 respuestas

La mejor respuesta

Puede usar una reducción anidada () de Object#entries() para iterar propiedades sin necesidad de codificar nombres de propiedades específicos en cualquier lugar

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)
2
charlietfl 7 sep. 2018 a las 14:43

Usando forEach como tú, pero for in adentro.

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);
0
Emeeus 7 sep. 2018 a las 14:28

Tomando la respuesta @charlietfl y editándola para IE (usando Object.keys en lugar de 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)
0
Mcestone 7 sep. 2018 a las 16:55

Puede tomar las entradas de los objetos para un recuento arbitrario de claves y valores.

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; }
0
Nina Scholz 7 sep. 2018 a las 14:23

Para lograr el resultado esperado, use Object.keys y dos bucles usando forEach

  1. El primer bucle con forEach manejará cada objeto
  2. Segundo bucle con Object.keys manejará las teclas de cada objeto y empujará a la nueva matriz con teclas
  3. Use Object.hasOwnProperty para ingresar el valor en newObj con las propiedades del objeto de matriz original
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 para referencia - https://codepen.io/nagasai/pen/MqOpWm?editors= 1010

0
Naga Sai A 7 sep. 2018 a las 14:35