Tengo una gran variedad de objetos:

var test = [{name: 'lorem', age: 20, color:'red'}, {name: 'lorem', weight: 1, height:5} , {name: 'hello', ipsum : 'dolor'}]

Me gustaría fusionarlos y agruparlos. El resultado esperado es:

var test = [{name: 'lorem', age : 20, color: 'red', weight : 1, height : 5}, {name: 'hello', ipsum : 'dolor'}]

La solución puede estar en vainilla, lodash o JQuery ...

EDITAR: Lo siento chicos, olvidé decir que tiene que estar escrito en ES5

EDITAR: Casi reescribí la propuesta de Goraks para ES5. Intenté _.clone para evitar usar el operador de propagación, pero no funciona

var r = _.values(_.reduce(test,function (acc, e) {
    acc[e.name] = {...(acc[e.name] || {}), ...e}; // this line is still in ES6
    return acc;
},{}));
0
frenchman100 24 jun. 2020 a las 17:55

3 respuestas

La mejor respuesta

Puede utilizar reduce y tomar Object.values. Aquí hay un ejemplo de trabajo:

var test = [{name: 'lorem', age: 20, color:'red'}, {name: 'lorem', weight: 1, height:5} , {name: 'hello', ipsum : 'dolor'}];

var result = Object.values(test.reduce((acc, e)=>{
    acc[e.name] = {...(acc[e.name] || {}), ...e};
    return acc;
},{}));

console.log(result);

También otro enfoque podría ser tomar valores Set (nombres únicos) y luego usar Object.assign para fusionar la matriz filtrada. Prueba esto:

var test = [{name: 'lorem', age: 20, color:'red'}, {name: 'lorem', weight: 1, height:5} , {name: 'hello', ipsum : 'dolor'}];

var result = [...new Set(test.map(({name})=>name))].map(n=>Object.assign(...test.filter(p=>p.name==n)));

console.log(result);
2
gorak 24 jun. 2020 a las 20:27

Puedes usar el siguiente método

var test = [
  { name: 'lorem', age: 20, color: 'red' },
  { name: 'lorem', weight: 1, height: 5 },
  { name: 'hello', ipsum: 'dolor' },
]

const finalResult = test.reduce((result, obj) => {
  if (result[obj.name]) {
    result[obj.name] = {
      ...result[obj.name],
      ...obj,
    }
  } else {
    result[obj.name] = { ...obj }
  }
  return result
}, {})

console.log(Object.values(finalResult))
1
Nithish 24 jun. 2020 a las 15:03

¡Esta función hará el truco!

(name se coloca en la parte inferior de cada objeto, pero eso no importa)
(puro JS)

function mergeList(list) {
  var temp = {};
  list.forEach(elem => {
    var name = elem.name;
    delete elem.name;
    temp[name] = {
      ...temp[name],
      ...elem
    }
  });
  var merged = [];
  Object.keys(temp).forEach(key => {
    var object = temp[key];
    object.name = key;
    merged.push(object);
  });
  return merged;
}

var test = [{
  name: 'lorem',
  age: 20,
  color: 'red'
}, {
  name: 'lorem',
  weight: 1,
  height: 5
}, {
  name: 'hello',
  ipsum: 'dolor'
}];

console.log(mergeList(test));
1
Antoni 24 jun. 2020 a las 15:21