Home > OS >  JavaScript: Removing all Objects that are equal in just a single attribute from Array
JavaScript: Removing all Objects that are equal in just a single attribute from Array

Time:04-07

I have an Array of Geography-Location-Objects of this kind:

   let markers = [
   {
    "markerOffset": 10,
    "name": "Plantation",
    "coordinates": ["9.85804","53.5233"]
   },
   {
    "markerOffset": 10,
    "name": "Roasting",
    "coordinates": ["29.85804","50.5233"]
   },
   {
    "markerOffset": 10,
    "name": "Packaging",
    "coordinates": ["29.85804","50.5233"]
   },
{
    "markerOffset": 10,
    "name": "Harbour",
    "coordinates": ["21.85804","51.5213"]
   },
]

How can I filter the array to remove duplicate objects with the same coordinates (such as element 2 and 3) and only leave one entry with the coordinates.

A Set wont work propably because of the differing name: attribute

CodePudding user response:

You'll need to loop through the markers array add unique markers (by their coordinates) to a new array. This second array will be used to compare the next marker in the loop.

const markers = [
  {
    markerOffset: 10,
    name: "Plantation",
    coordinates: ["9.85804", "53.5233"],
  },
  {
    markerOffset: 10,
    name: "Roasting",
    coordinates: ["29.85804", "50.5233"],
  },
  {
    markerOffset: 10,
    name: "Packaging",
    coordinates: ["29.85804", "50.5233"],
  },
  {
    markerOffset: 10,
    name: "Harbour",
    coordinates: ["21.85804", "51.5213"],
  },
];

const filteredMarkers = [];

for (let i = 0, length = markers.length; i < length; i  ) {
  let duplicate = false;
  for (let j = 0, length = filteredMarkers.length; j < length; j  ) {
    const [lat1, lon1] = markers[i].coordinates;
    const [lat2, lon2] = filteredMarkers[j].coordinates;
    if (lat1 === lat2 && lon1 === lon2) {
      duplicate = true;
      break;
    }
  }
  if (!duplicate) {
    filteredMarkers.push(markers[i]);
  }
}

console.log(filteredMarkers);

CodePudding user response:

Simple compare and build a new array. This doesn't care about the name attribute and just uses the first one that comes along

let markers = [
   { "markerOffset": 10, "name": "Plantation", "coordinates": ["9.85804","53.5233"] },
   { "markerOffset": 10, "name": "Roasting", "coordinates": ["29.85804","50.5233"] },
   { "markerOffset": 10, "name": "Packaging", "coordinates": ["29.85804","50.5233"] },
   { "markerOffset": 10, "name": "Harbour",  "coordinates": ["21.85804","51.5213"] },
]

let results = [];
markers.forEach(marker => {
    if(!results.find(m => m.coordinates[0] === marker.coordinates[0] &&  m.coordinates[1] === marker.coordinates[1] )) results.push(marker);
})

console.log(results);

CodePudding user response:

A nice simple way is to use findIndex using the coordinates, you can just toString these to make the find even easier, use this in a filter, and if the index is the same it's the first of a duplicate or not a duplicate.

eg.

const markers = [
  {
    markerOffset: 10,
    name: "Plantation",
    coordinates: ["9.85804", "53.5233"],
  },
  {
    markerOffset: 10,
    name: "Roasting",
    coordinates: ["29.85804", "50.5233"],
  },
  {
    markerOffset: 10,
    name: "Packaging",
    coordinates: ["29.85804", "50.5233"],
  },
  {
    markerOffset: 10,
    name: "Harbour",
    coordinates: ["21.85804", "51.5213"],
  },
];

console.log(
  markers.filter(
    (m,ix) => markers.findIndex(c =>
      c.coordinates.toString() ===
      m.coordinates.toString()) === ix)
);

Bonus, if you wanted the last of a duplicate, you can just change findIndex to findLastIndex

CodePudding user response:

Another way to make an array unique by a certain property:

const markers=[{markerOffset:10,name:"Plantation",coordinates:["9.85804","53.5233"]},{markerOffset:10,name:"Roasting",coordinates:["29.85804","50.5233"]},{markerOffset:10,name:"Packaging",coordinates:["29.85804","50.5233"]},{markerOffset:10,name:"Harbour",coordinates:["21.85804","51.5213"]}];

const uniqByCoords = Object.values(markers.reduce((acc, market) => {
    acc[String(market.coordinates)] ??= market; //return first market item in array as uniq. 
    // If you need the last one replace ??= to =
    return acc;
}, {}));

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

  • Related