Tengo una lista de diccionarios como este que pueden contener duplicados según algunas propiedades del diccionario (no todas las propiedades):
const data = [{ name: 'v', latitude: '30.0', longitude: '25.0' }, { name: 'w', latitude: '30.0', longitude: '25.0' }, { name: 'x', latitude: '45.9', longitude: '50.2' }, { name: 'y', latitude: '40.5', longitude: '85.7' }, { name: 'z', latitude: '40.5', longitude: '85.7' }];Aquí, dos diccionarios se consideran duplicados si comparten la misma longitud y latitud.
El objetivo es reducir esta lista 1D, agrupando todos los duplicados de un tipo en una lista anidada. Por ejemplo, si tenemos tres duplicados con las mismas coordenadas, deberían ir a su propia lista anidada, mientras que dos duplicados de otra coordenada van a una lista anidada diferente. Incluso una coordenada independiente sin duplicados debe ir a su propia lista anidada. Queremos terminar con una lista en la que cada elemento sea una lista que represente una coordenada única.
Salida deseada:
[ [ { name: 'v', latitude: '30.0', longitude: '25.0' }, { name: 'w', latitude: '30.0', longitude: '25.0' } ], [ { name: 'x', latitude: '45.9', longitude: '50.2' } ], [ { name: 'y', latitude: '40.5', longitude: '85.7' }, { name: 'z', latitude: '40.5', longitude: '85.7' } ] ];EDITAR: se corrigió la salida deseada para que todos los elementos sean listas.
Comenzaría poniendo cada punto de datos en un objeto. Usaría la coordenada (lat, lng) como clave que apunta a una matriz para cada coordenada única. A medida que itera a través de los puntos de datos, puede agregar cada uno a su matriz respectiva en su objeto.
Luego itere a través de los valores de ese objeto que acaba de crear. Cada valor debe ser una matriz. Si la longitud de esa matriz es 1, puede simplemente agregar el objeto a su matriz de salida, pero si es mayor que 1, puede agregar la matriz completa a su matriz de salida.
Voilá.
const data = [{ name: 'v', latitude: '30.0', longitude: '25.0' }, { name: 'w', latitude: '30.0', longitude: '25.0' }, { name: 'x', latitude: '45.9', longitude: '50.2' }, { name: 'y', latitude: '40.5', longitude: '85.7' }, { name: 'z', latitude: '40.5', longitude: '85.7' }]; let obj = {}; data.forEach(e => { let key = `${e.latitude},${e.longitude}`; if(obj[key] == undefined) obj[key] = []; obj[key].push(e); }); let output = []; Object.values(obj).forEach(e => { if(e.length == 1) output.push(e[0]); else output.push(e); }); console.log(output);aunque hay muchas opciones para esto, preferiría esta solución usando reduce .
Básicamente, construimos un objeto usando como claves las diferentes latitude y longitude para obtener una clave única, si se repite, creamos una matriz (si no se creó antes) y luego empujamos el elemento.
Creo que esto es muy elegante, legible y eficiente para sus propósitos.
nota: como lo solicitó el usuario, se corrigió para tener todo en matrices.
const data = [{ name: 'v', latitude: '30.0', longitude: '25.0' }, { name: 'w', latitude: '30.0', longitude: '25.0' }, { name: 'x', latitude: '45.9', longitude: '50.2' }, { name: 'y', latitude: '40.5', longitude: '85.7' }, { name: 'z', latitude: '40.5', longitude: '85.7' }]; const reducer = (accum, cv, i) => { // create a key using the lat and lng const key = `${cv.latitude}-${cv.longitude}`; // if the key was already there, we need to push it. if (accum[key]) { accum[key] = [...accum[key], cv] } else { // if not, we just create an array with the entry accum[key] = [cv]; } return accum; }; const objectMapped = data.reduce(reducer, {}); // then we get an object, to get the values we use this function. const result = Object.values(objectMapped); console.log(result);Tu puedes hacer:
const data = [{ name: 'v', latitude: '30.0', longitude: '25.0' },{ name: 'w', latitude: '30.0', longitude: '25.0' },{ name: 'x', latitude: '45.9', longitude: '50.2' },{ name: 'y', latitude: '40.5', longitude: '85.7' },{ name: 'z', latitude: '40.5', longitude: '85.7' },] const result = Object.values(data.reduce((a, c) => { const k = `${c.latitude}${c.longitude}` return (a[k] = [...(a[k] || []), c], a) }, {})) console.log(result)