按最近位置对 PHP 数组进行排序

Sorting PHP array by closest location

提问人:Viacheslav Ravdin 提问时间:7/7/2023 更新时间:7/7/2023 访问量:51

问:

我有一个带有 Paysera 包裹机的阵列:

Array
(
    [0] => Array
        (
            [id] => PMFOzGmlcQ-9GmEt5vj9JTGals_1nI87Lm
            [shipment_gateway_code] => lp
            [code] => 0199
            [address] => Array
                (
                    [country] => LT
                    [city] => Vilnius
                    [street] => Žirmūnų g. 48A
                    [postal_code] => 09226
                )

            [coordinates] => Array
                (
                    [latitude] => 54.70274
                    [longitude] => 25.30368
                )

            [location_name] => Express Market
            [enabled] => 1
        )

    [1] => Array
        (
            [id] => PMBBGl0TsF1vuv8YqeLsn4gyWwGB9-vd98
            [shipment_gateway_code] => lp
            [code] => 0198
            [address] => Array
                (
                    [country] => LT
                    [city] => Vilnius
                    [street] => Lazdynėlių g. 23
                    [postal_code] => 04126
                )

            [coordinates] => Array
                (
                    [latitude] => 54.66283
                    [longitude] => 25.19253
                )

            [location_name] => Maxima
            [enabled] => 1
        )
)

此外,我在数组中也有用户的坐标:

Array
    (
        [latitude] => 54.70274
        [longitude] => 25.30368
    )

我必须按离用户最近的位置对我的第一个数组进行排序,但我真的不明白该怎么做。

我尝试了以下解决方案,但似乎什么也没做:

$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);
});

请帮助我实现我的目标。谢谢!

php 纬度-经度

评论

2赞 Chris Haas 7/7/2023
忽略“排序”,第一步实际上是获得两点之间的距离。我已经很久没有这样做了,但乍一看,您使用的算法似乎比我记得的要简单,尽管我可能是错的。
0赞 Barmar 7/7/2023
要计算与纬度和经度的距离,请使用 levenshtein()
0赞 Viacheslav Ravdin 7/7/2023
@Barmar你能说得更具体一点吗?也许是一些代码示例?
1赞 Barmar 7/7/2023
对不起,这是错误的。Levenshtein 是字符串之间的编辑距离。我的意思是Haversine:stackoverflow.com/questions/14750275/haversine-formula-with-php
1赞 Barmar 7/7/2023
或者 stackoverflow.com/questions/10053358/......

答:

1赞 Viacheslav Ravdin 7/7/2023 #1

据我从上面的评论和维基百科中了解到,文森特公式是计算距离的最准确公式。

所以我想出了以下代码:

$arParcelMachines = Array(); // $arParcelMachines is an array of parcell machines from Paysera

if ($latitude && $longitude) { // $latitude && $longitude are user's coordinates
    foreach ($arParcelMachines as &$arParcelMachine) {
        $arParcelMachine["distance"] = getDistance($latitude, $longitude, $arParcelMachine["coordinates"]["latitude"], $arParcelMachine["coordinates"]["longitude"]);
    }

    usort($arParcelMachines, function($a, $b) {
        return $a["distance"] - $b["distance"];
    });
}

function getDistance($fromLatitude, $fromLongitude, $toLatitude, $toLongitude, $radius = 6371000) { // Vincenty's formula
    $fromLatitude = deg2rad($fromLatitude);
    $fromLongitude = deg2rad($fromLongitude);
    $toLatitude = deg2rad($toLatitude);
    $toLongitude = deg2rad($toLongitude);
  
    $deltaLongitude = abs($fromLongitude - $toLongitude);
  
    $centralAngle = atan2(sqrt(pow(cos($toLatitude) * sin($deltaLongitude), 2) + pow(cos($fromLatitude) * sin($toLatitude) - sin($fromLatitude) * cos($toLatitude) * cos($deltaLongitude), 2)), sin($fromLatitude) * sin($toLatitude) + cos($fromLatitude) * cos($toLatitude) * cos($deltaLongitude));
    
    return $radius * $centralAngle;
}