这可能很困难,我想根据lat和lon的最接近匹配搜索以下多维数组,并返回该子数组。
例如,我已经设置了以下值:
Lat=50.6000,Lon=-741.5000
我想搜索以下内容,并返回最匹配的数组。或者按最接近到最远的方式对整件事进行排序。
更好的方法是对列表进行排序,使最接近的纬度/经度先向下到最远离的纬度/纬度。我不需要的是按降序排列。例如,我需要最接近上面的预设值。有人有主意吗?
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
)
)
这里的函数就是这样做的。。。。然而,它返回具有两个主要元素latitudes
和longitudes
的多维数组。经度包含最近经度值的所有排序条目,"纬度"也包含最近纬度的排序条目。默认情况下,函数仅在纵向和纵向上返回最接近的匹配。但是,将false作为最后一个Parameter传递会返回所有排序的条目。下面的代码说明了这一切:
<?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)
考虑:
$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
我想如果我这样做的话,我可以组合计算并按顺序返回完整的数组。需要做一些测试,但到目前为止看起来是正确的@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;
}