I have a list of dictionaries like this that may contain duplicates based on a few dictionary properties (not all properties):
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'
}];
Here, two dictionaries are considered duplicates if they share the same longitude and latitude.
The goal is to reduce this 1D list, grouping all duplicates of one kind into a nested list. For example, if we have three duplicates with the same coordinates, they should go into their own nested list, whereas two duplicates of another coordinate go into a different nested list. Even a standalone coordinate with no duplicates should go into its own nested list. We want to end up with a list where every item is a list that represents a unique coordinate.
Desired output:
[
[
{
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'
}
]
];
EDIT: Corrected desired output so that all items are lists.
I would start by putting every data point into an object. I would use the coordinate (lat,lng) as a key which points to an array for each unique coordinate. As you iterate through the data points, you can add each one to its respective array in your object.
Then iterate through the values of that object you just created. Each value should be an array. If the length of that array is 1, you can just add the object to your output array, but if it's greater than 1, you can add the entire array to your output array.
Voila.
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);
altough there are many options to this, I would prefer this solution using reduce.
basically, we build an object using as keys the different latitude and longitude to get a unique key, if it is repeated we create an array (if not created before) and then push the item.
I think this is very elegant readable and efficient for your purpouses.
note: as the user request, corrected to have everything in arrays.
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);
You can do:
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)