这可能很难,我想基于lat和lon的最接近匹配搜索以下多维数组并返回该子数组。
例如,我将设置以下值:
Lat = 50.6000,Lon = -74.15000
我想搜索以下内容,并返回最接近匹配的数组。或者最接近最远的整个事情。
更好的方法是对列表进行排序,使最近的纬度/经度首先下降到最远的距离。我不需要的是它按降序排序。例如,我需要最接近上面的预设值。有人有想法吗?
Array
(
[0] => Array
(
[zipcode] => 28299
[latitude] => 36.234982
[longitude] => -81.913799
[cityname] => ACME
)
[1] => Array
(
[zipcode] => 17198
[latitude] => 50.735880
[longitude] => -74.143855
[cityname] => NEWLAND
)
[2] => Array
(
[zipcode] => 12203
[latitude] => 41.711931
[longitude] => -75.011806
[cityname] => ACE
)
)
答案 0 :(得分:1)
这里的函数就是这样....但是,它返回一个包含2个主要元素latitudes
和longitudes
的多维数组。经度包含最近经度值的所有已排序条目,“纬度”也包含最近纬度值的已排序条目。默认情况下,函数仅在纬度和纵向上返回非常接近的匹配。但是,在最后一个参数返回所有已排序的条目时传递false。下面的代码说明了一切:
<?php
$arrGeoData = array(
array(
"zipcode" => 28299,
"latitude" => 36.234982,
"longitude" => -81.913799,
"cityname" => "ACME",
),
array(
"zipcode" => 17198,
"latitude" => 50.735880,
"longitude" => -74.143855,
"cityname" => "NEWLAND",
),
array(
"zipcode" => 12203,
"latitude" => 41.711931,
"longitude" => -75.011806,
"cityname" => "ACE",
),
);
$nearestLongLat = sortByNearestLatLong($arrGeoData, 50.6000, -74.15000);
var_dump(nearestLongLat);
function sortByNearestLatLong($geoData, $lat, $long, $returnNearestOnly=true){
// CREATE AN ARRAY FOR USE INSIDE THE FUNCTION
$arrCloseMatchLat = array();
$arrCloseMatchLong = array();
$matchedGeoSet = array();
// LOOP THROUGH ALL THE $geoData ARRAY AND SUBTRACT THE GIVEN LAT & LONG VALUES
// FROM THOSE CONTAINED IN THE ORIGINAL ARRAY: $geoData
// WE KNOW THAT THE SMALLER THE RESULT OF THE SUBTRACTION; THE CLOSER WE ARE
// WE DO THIS FOR BOTH THE LONGITUDE & LATITUDE... HENCE OUR ARRAY:
// $arrCloseMatchLat AND $arrCloseMatchLong RESPECTIVELY
foreach($geoData as $iKey=>$arrGeoStrip){
$arrCloseMatchLat[$iKey] = abs(floatval( ($arrGeoStrip['latitude']) - $lat ));
$arrCloseMatchLong[$iKey] = abs(floatval( ($arrGeoStrip['longitude']) - $long ));
}
// WE SORT BOTH ARRAYS NUMERICALLY KEEPING THE KEYS WHICH WE NEED FOR OUR FINAL RESULT
asort($arrCloseMatchLat, SORT_NUMERIC);
asort($arrCloseMatchLong, SORT_NUMERIC);
// WE CAN RETURN ONLY THE RESULT OF THE FIRST, CLOSEST MATCH
if($returnNearestOnly){
foreach($arrCloseMatchLat as $index=>$difference){
$matchedGeoSet['latitudes'][] = $geoData[$index];
break;
}
foreach($arrCloseMatchLong as $index=>$difference){
$matchedGeoSet['longitudes'][] = $geoData[$index];
break;
}
// OR WE CAN RETURN THE ENTIRE $geoData ARRAY ONLY SORTED IN A "CLOSEST FIRST" FASHION...
// WE DO THIS FOR BOTH THE LONGITUDE & LATITUDE RESPECTIVELY SO WE END UP HAVING 2
// ARRAYS: ONE THAT SORTS THE CLOSEST IN TERMS OF LONG VALUES
// AN ONE THAT SORTS THE CLOSEST IN TERMS OF LAT VALUES...
}else{
foreach($arrCloseMatchLat as $index=>$difference){
$matchedGeoSet['latitudes'][] = $geoData[$index];
}
foreach($arrCloseMatchLong as $index=>$difference){
$matchedGeoSet['longitudes'][] = $geoData[$index];
}
}
return $matchedGeoSet;
}
行: $ nearestLongLat = sortByNearestLatLong($ arrGeoData,50.6000,-74.15000); 上面的var_dump(nearestLongLat); 会产生如下所示的内容。注意纬度和经度键
array (size=2)
'latitudes' =>
array (size=1)
0 =>
array (size=4)
'zipcode' => int 17198
'latitude' => float 50.73588
'longitude' => float -74.143855
'cityname' => string 'NEWLAND' (length=7)
'longitudes' =>
array (size=1)
0 =>
array (size=4)
'zipcode' => int 17198
'latitude' => float 50.73588
'longitude' => float -74.143855
'cityname' => string 'NEWLAND' (length=7)
现在,我们再次尝试使用一组不同的坐标: $ nearestLongLat = sortByNearestLatLong($ arrGeoData,25.6000,-84.15000); 的var_dump($ nearestLongLat); 即可。这会产生:
array (size=2)
'latitudes' =>
array (size=1)
0 =>
array (size=4)
'zipcode' => int 28299
'latitude' => float 36.234982
'longitude' => float -81.913799
'cityname' => string 'ACME' (length=4)
'longitudes' =>
array (size=1)
0 =>
array (size=4)
'zipcode' => int 28299
'latitude' => float 36.234982
'longitude' => float -81.913799
'cityname' => string 'ACME' (length=4)
答案 1 :(得分:0)
考虑:
$cities = <your array>;
$point = array(
'latitude' => 50.6000,
'longitude' => -74.15000
);
function distance($a, $b) {
return sqrt(
pow($a['latitude'] - $b['latitude'], 2)
+ pow($a['longitude'] - $b['longitude'], 2));
}
usort($cities, function($p, $q) {
global $point;
return distance($p, $point) - distance($q, $point);
});
这使用了朴素的欧几里德距离公式,为了更准确的计算,将distance
替换为此处列出的公式之一:https://en.wikipedia.org/wiki/Geographical_distance
答案 2 :(得分:0)
我想我可以将计算结合起来,并按顺序返回完整数组,如果我这样做的话。需要做一些测试,但到目前为止它看起来是正确的。 @poiz
function sort2ByNearestLatLong($geoData, $lat, $long, $returnNearestOnly=false){
$arrCloseMatch = array();
$matchedGeoSet = array();
// LOOP THROUGH ALL THE $geoData ARRAY AND SUBTRACT THE GIVEN LAT & LONG VALUES
// FROM THOSE CONTAINED IN THE ORIGINAL ARRAY: $geoData
// WE KNOW THAT THE SMALLER THE RESULT OF THE SUBTRACTION; THE CLOSER WE ARE
// WE DO THIS FOR BOTH THE LONGITUDE & LATITUDE... HENCE OUR ARRAY
// $arrClostMatch and add the values calculated for Lat/Lon:
foreach($geoData as $iKey=>$arrGeoStrip){
$arrCloseMatch[$iKey] = abs(floatval( ($arrGeoStrip['latitude']) - $lat )) + abs(floatval( ($arrGeoStrip['longitude']) - $long ));
}
// SORT ARRAY NUMERICALLY KEEPING THE KEYS WHICH WE NEED FOR OUR FINAL RESULT
asort($arrCloseMatch, SORT_NUMERIC);
// RETURN CLOSEST OR FULL LIST
foreach($arrCloseMatch as $index=>$difference){
$matchedGeoSet['latitudes'][] = $geoData[$index];
if ($returnNearestOnly==true) {
break;
}
}
return $matchedGeoSet;
}