theblueone theblueone - 4 months ago 10
Javascript Question

Create array of unique objects by property

I created an array of objects like so:

var places = [];
var a = {};
a.lat = 12.123;
a.lng = 13.213;
a.city = "New York";

places.push(a);

var b = {};
b.lat = 3.123;
b.lng = 2.213;
b.city = "New York";

places.push(b);

...


I'm trying to create a new array that filters the places to only contains objects that don't have the same city property (lat/lng duplicates are ok). Is there a built in JS or Jquery function to achieve this?

Answer

I'd probably use a flags object during the filtering, like this:

var flags = {};
var newPlaces = places.filter(function(entry) {
    if (flags[entry.city]) {
        return false;
    }
    flags[entry.city] = true;
    return true;
});

That uses Array#filter from ECMAScript5 (ES5), which is one of the ES5 additions that can be shimmed (search for "es5 shim" for several options).

You can do it without filter, of course, it's just a bit more verbose:

var flags = {};
var newPlaces = [];
var index;
for (index = 0; index < places.length; ++index) {
    if (!flags[entry.city]) {
        flags[entry.city] = true;
        newPlaces.push(entry);
    }
});

Both of the above assume the first object with a given city should be kept, and all other discarded.


Note: As user2736012 points out below, my test if (flags[entry.city]) will be true for cities with names that happen to be the same as properties that exist on Object.prototype such as toString. Very unlikely in this case, but there are two ways to avoid the possibility:

  • Use hasOwnProperty for the test, e.g. if (flags.hasOwnProperty(entry.city))

  • (My usual preferred solution) Put a prefix on that you know doesn't exist for any Object.prototype property, such as xx:

    var key = "xx" + entry.city;
    if (flags[key]) {
        // ...
    }
    flags[key] = true;