1

Possible Duplicate:
How to sort an array of javascript objects?

Well, more preciselly, I have the following class:

function Location(name, latitude, longitude){
this.latitude = latitude;
this.longitude = longitude;
this.name = name;
}

And I want to sort an array of these objects, by order of proximity to a given Location (an object of a class like this one).

Community
  • 1
  • 1
EBM
  • 1,067
  • 2
  • 11
  • 20

5 Answers5

7

You'll need a comparator function:

function sortLocations(locations, lat, lng) {
  function dist(l) {
    return (l.latitude - lat) * (l.latitude - lat) +
      (l.longitude - lng) * (l.longitude - lng);
  }

  locations.sort(function(l1, l2) {
    return dist(l1) - dist(l2);
  });
}

I don't bother with the square roots there because I don't think it's necessary. Also I'm not accounting for any weirdness from spherical geometry, because again I don't think it's worth the complexity. However, if you have your own existing way to compute a distance, it could be plugged in instead of what I typed above.

You'd call that by just passing your array, plus the reference point coordinates, to that function. If you wanted to pass a "Location" instance instead it should be clear what to change.

Pointy
  • 405,095
  • 59
  • 585
  • 614
4

See: Sorting an array of JavaScript objects

The other answer's simple lat1-lat2 + lon1-lon2 formula is incorrect for even a mathematical 2-d plane, much more so for the ellipsoidal Earth. Unless the distance doesn't really need to be accurate, you should use the haversine formula as your sorting function.

from: http://www.movable-type.co.uk/scripts/latlong.html

var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var lat1 = lat1.toRad();
var lat2 = lat2.toRad();

var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c;
Community
  • 1
  • 1
you786
  • 3,659
  • 5
  • 48
  • 74
1

You want to pass a function to Array.prototype.sort. This link has a pretty good explanation of it. I'm aware that this isn't proper for spherical geometry, but you'll want something like this:

var home = new Location("Home", 40, -50);
arr.sort(function(a, b){
    var dist1 = Math.sqrt(Math.pow(home.latitude-a.latitude, 2) + Math.pow(home.longitude-a.longitude, 2)),
        dist2 = Math.sqrt(Math.pow(home.latitude-b.latitude, 2) + Math.pow(home.longitude-b.longitude, 2));
    if (dist1 < dist2) { 
        return -1;
    }
    else {
        return 1;
    }
});
lbstr
  • 2,822
  • 18
  • 29
1
function Location(name, latitude, longitude){
this.latitude = latitude;
this.longitude = longitude;
this.name = name;
};

this.locations.push(new Location());

 this.locations.sort(function (a, b) { return a.latitude - b.latitude ; });

You need to have your Location stored in an array.

Vinyl Windows
  • 503
  • 1
  • 7
  • 19
1
Location.distance = function ( loc1, loc2 ) {
    return Math.sqrt(
        Math.pow( loc2.longitude - loc1.longitude, 2 ) +
        Math.pow( loc2.latitude - loc1.latitude, 2 )
    );
};

Location.prototype.sortByProximity = function ( arr ) {
    var that = this;
    arr.sort(function ( a, b ) {
        return Location.distance( that, a ) - Location.distance( that, b );
    });
};

First, you have a static function Location.distance which takes two Location instances and returns a value representing their relative distance.

Second, you have a sortByProximity method which is invoked as a method on Location instances, and which expects an array of Location instances as its first argument.

Usage:

baseLocation.sortByProximity( locArr );
// locArr is now sorted in regard to baseLocation

Live demo: http://jsfiddle.net/hGp66/

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385