如何根据短距离Javascript对数组进行排序

时间:2016-03-29 15:00:53

标签: javascript arrays angularjs sorting

我想对一个数组进行排序,使每个元素与前一个位置的距离最短。

数组就像那样

locations=[{"loc1",lat,long},{"loc2",lat,long},{"loc3",lat,long},{"loc4",lat,long},{"loc5",lat,long}]

计算距离的函数是:

var distance = function(lat1, lon1, lat2, lon2)
{
  var radlat1 = Math.PI * lat1/180;
  var radlat2 = Math.PI * lat2/180;
  var theta = lon1-lon2;
  var radtheta = Math.PI * theta/180;
  var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
  dist = Math.acos(dist);
  dist = dist * 180/Math.PI;
  dist = dist * 60 * 1.1515;
  dist = dist * 1.609344 ;

  return dist;
}

此函数在传递值时提供两个位置之间的距离。

起点是位置数组的第一个元素 现在我想要一个将采用数组并返回已排序数组的函数。

4 个答案:

答案 0 :(得分:0)

您需要在排序函数中执行距离计算:

由于距离计算非常密集,因此对象中的缓存距离会更快,因此您在排序方法中不会多次计算相同的距离:

var startingLoc = {lat:0.000,lng:0.000};//your starting location;
var distanceCache = {}; //a cache to hold your distance calculations

//sort the locations - assumes loc1 is {lat:some number, lng: some number}
locations.sort(function(loc1,loc2) {
    var loc1Key = loc1.lat+'-'+loc1.lng;
    var loc2Key = loc2.lat+'-'+loc2.lng;

    if(!distanceCache.hasOwnProperty(loc1Key)) {
      distanceCache[loc1Key] = distance(startingLoc.lat,startingLoc.lng,loc1.lat,loc1.lng);
    }

    if(!distanceCache.hasOwnProperty(loc2Key)) {
      distanceCache[loc2Key] = distance(startingLoc.lat,startingLoc.lng,loc2.lat,loc2.lng);
    }

    return distanceCache[loc1Key] - distanceCache[loc2Key];

 });

distanceCache = null; //done with distanceCache

答案 1 :(得分:0)

你可能会在这个上面找个漂亮的大兔子洞。我先来看看你是否可以使用Maps API Google Map V3, how to get list of best driving route for multiple destinations?optimizeWaypoints设置旨在以最佳驾驶顺序返回位置列表。

显然这与纯距离比较不同,但它可能适合您的需要。

答案 2 :(得分:0)

您可以为Array原型上的sort方法提供自定义函数,如下所示:



locations = [
  ["loc1", 1, 1],
  ["loc2", 3, 3],
  ["loc3", 2, 2],
  ["loc4", 5, 4],
  ["loc5", 3, 5]
];

var distance = function(lat1, lon1, lat2, lon2) {
  var radlat1 = Math.PI * lat1 / 180;
  var radlat2 = Math.PI * lat2 / 180;
  var theta = lon1 - lon2;
  var radtheta = Math.PI * theta / 180;
  var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
  dist = Math.acos(dist);
  dist = dist * 180 / Math.PI;
  dist = dist * 60 * 1.1515;
  dist = dist * 1.609344;

  return dist;
};

locations.sort(function(a, b) {
  var origLat = 0,
    origLong = 0;

  return distance(origLat, origLong, a[1], a[2]) - distance(origLat, origLong, b[1], b[2]);
});

console.log(locations)




答案 3 :(得分:0)

如果没有真正的位置,就不会测试,但下面的内容应该可以完成这项工作:

(我不知道谷歌地图API,也许你可以找到更好的方法来做到这一点......)

var locations = [{
		name : "loc1",
		lat : 1001,
		long : 2001
	}, {
		name : "loc2",
		lat : 150,
		long : 630
	}, {
		name : "loc3",
		lat : 151,
		long : 631
	}, {
		name : "loc4",
		lat : 850,
		long : 56
	}, {
		name : "loc5",
		lat : 960,
		long : 698
	}
];

var distance = function (lat1, lon1, lat2, lon2) {
	var radlat1 = Math.PI * lat1 / 180;
	var radlat2 = Math.PI * lat2 / 180;
	var theta = lon1 - lon2;
	var radtheta = Math.PI * theta / 180;
	var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
	dist = Math.acos(dist);
	dist = dist * 180 / Math.PI;
	dist = dist * 60 * 1.1515;
	dist = dist * 1.609344;

	return dist;
}

var locationWithDistFromPrevious = locations.map(function (l, i) {
		if (i === 0) {
			l.dist = 0;
		} else {
			l.dist = distance(l.lat, l.long, locations[i - 1].lat, locations[i - 1].long)
		}
		return l;
	}).sort(function (a, b) {
		return a.dist - b.dist
	});

var locationWithDistFromFirst = locations.map(function (l, i) {
		if (i === 0) {
			l.dist = 0;
		} else {          
			l.dist = distance(l.lat, l.long, locations[0].lat, locations[0].long)
		}
		return l;
	}).sort(function (a, b) {
		return a.dist - b.dist
	});


document.getElementById("resultFromPrev").textContent = JSON.stringify(locationWithDistFromPrevious, null, 4);
document.getElementById("resultFromFirst").textContent = JSON.stringify(locationWithDistFromFirst, null, 4);
<body>
  Sort by previous item<br/>
  <pre id="resultFromPrev"></pre><br/>
  Sort by first item dist <br/>
  <pre id="resultFromFirst"></pre><br/>
</body>