Home > Software engineering >  How can I group by multiple fields?
How can I group by multiple fields?

Time:11-28

I have this array:

[ {
  id_base: 2,
  nombre_base: 'Hayama',
  nombre_flota: 'Browseblab',
  matricula: '#b65e9e',
  id_vehiculo: 3
},  {
  id_base: 2,
  nombre_base: 'Hayama',
  nombre_flota: 'Browseblab',
  matricula: '#b65e9e',
  id_vehiculo: 3
},  {
  id_base: 2,
  nombre_base: 'Hayama',
  nombre_flota: 'Browseblab',
  matricula: '#a606f8',
  id_vehiculo: 4
},  {
  id_base: 1,
  nombre_base: 'Cabitan',
  nombre_flota: 'Browseblab',
  matricula: '#8f72c2',
  id_vehiculo: 1
},  {
  id_base: 1,
  nombre_base: 'Cabitan',
  nombre_flota: 'Browseblab',
  matricula: '#8f72c2',
  id_vehiculo: 1
}]

And i want it to be grouped like this:

[{
  id_base: 2,
  nombre_base: 'Hayama',
  nombre_flota: 'Browseblab',
  [{
    matricula: '#b65e9e',
    id_vehiculo: 3
  }, {
    matricula: '#a606f8',
    id_vehiculo: 4
  }]
}, {
  id_base: 1,
  nombre_base: 'Cabitan',
  nombre_flota: 'Browseblab',
  [{
    matricula: '#8f72c2',
    id_vehiculo: 1
  }, {
    matricula: '#8f72c2',
    id_vehiculo: 1
  }]
}]

I have tried this:

let agrupadoBases = result.reduce((group, linea) => {
  const { id_base } = linea
  group[id_base] = group[id_base] ?? [] 
  delete linea.id_base 
  group[id_base].push(linea) 
  return group
}, {})

But it only separates id_base from the rest

{ '1': [ RowDataPacket { nombre_base: 'Cabitan', nombre_flota: 'Browseblab', matricula: '#8f72c2', id_vehiculo: 1 }, ], '2': [ RowDataPacket { nombre_base: 'Hayama', nombre_flota: 'Browseblab', matricula: '#b65e9e', id_vehiculo: 3 }, RowDataPacket { nombre_base: 'Hayama', nombre_flota: 'Browseblab', matricula: '#a606f8', id_vehiculo: 4 } ] }

CodePudding user response:

It's not perfect but it does the job.

I've created an empty object and I go through every object in your data array. If the object with the same id_base is present in the final object I only append another child to the array. If the object isn't there yet I push it into the array with some initial data.

const data = [{
  id_base: 2,
  nombre_base: 'Hayama',
  nombre_flota: 'Browseblab',
  matricula: '#b65e9e',
  id_vehiculo: 3
}, {
  id_base: 2,
  nombre_base: 'Hayama',
  nombre_flota: 'Browseblab',
  matricula: '#b65e9e',
  id_vehiculo: 3
}, {
  id_base: 2,
  nombre_base: 'Hayama',
  nombre_flota: 'Browseblab',
  matricula: '#a606f8',
  id_vehiculo: 4
}, {
  id_base: 1,
  nombre_base: 'Cabitan',
  nombre_flota: 'Browseblab',
  matricula: '#8f72c2',
  id_vehiculo: 1
}, {
  id_base: 1,
  nombre_base: 'Cabitan',
  nombre_flota: 'Browseblab',
  matricula: '#8f72c2',
  id_vehiculo: 1
}];

const expected = [{
  id_base: 2,
  nombre_base: 'Hayama',
  nombre_flota: 'Browseblab',
  someUnknownKey: [{
      matricula: '#b65e9e',
      id_vehiculo: 3,
    },
    {
      matricula: '#a606f8',
      id_vehiculo: 4
    }
  ]
}, {
  id_base: 1,
  nombre_base: 'Cabitan',
  nombre_flota: 'Browseblab',
  someUnknownKey: [{
      matricula: '#8f72c2',
      id_vehiculo: 1
    },
    {
      matricula: '#8f72c2',
      id_vehiculo: 1
    }
  ],
}];

let mappedData = [];

data.forEach((v) => {
  const parentIndex = mappedData.findIndex((mappedDataEntry) => mappedDataEntry.id_base === v.id_base);

  if (parentIndex === -1) {
    mappedData.push({
      id_base: v.id_base,
      nombre_base: v.nombre_base,
      nombre_flota: v.nombre_flota,
      someUnknownKey: [{
        matricula: v.matricula,
        id_vehiculo: v.id_vehiculo
      }]
    });

    return;
  }

  const newItem = {
    matricula: v.matricula,
    id_vehiculo: v.id_vehiculo
  };

  mappedData[parentIndex] = {
    ...mappedData[parentIndex],
    someUnknownKey: [
      ...mappedData[parentIndex].someUnknownKey,
      newItem,
    ]
  }
});

console.log(mappedData);

CodePudding user response:

You could separate the outer properties and take the rest foor the nested data.

const
    data = [{ id_base: 2, nombre_base: 'Hayama', nombre_flota: 'Browseblab', matricula: '#b65e9e', id_vehiculo: 3 }, { id_base: 2, nombre_base: 'Hayama', nombre_flota: 'Browseblab', matricula: '#b65e9e', id_vehiculo: 3 }, { id_base: 2, nombre_base: 'Hayama', nombre_flota: 'Browseblab', matricula: '#a606f8', id_vehiculo: 4 }, { id_base: 1, nombre_base: 'Cabitan', nombre_flota: 'Browseblab', matricula: '#8f72c2', id_vehiculo: 1 }, { id_base: 1, nombre_base: 'Cabitan', nombre_flota: 'Browseblab', matricula: '#8f72c2', id_vehiculo: 1 }],
    result = Object.values(data.reduce((r, { id_base, nombre_base, nombre_flota, ...o }) => {
        r[id_base] ??= { id_base, nombre_base, nombre_flota, data: [] };
        r[id_base].data.push(o);
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

  • Related