Нужна помощь, как использовать preg_replace_callback - PullRequest
1 голос
/ 22 апреля 2019

У меня есть этот код, который возвращает:

float(-70.869444444444)

Я вижу, используя var_dump, что он находит все координаты, но отображается только одна.

Как изменить приведенный ниже код для отображения всех координат, переданных в формате градусов, а также для отображения текста?

Требуемый результат должен быть:

-70,869 -6,35 тестировать -127,49 больше тестировать вторую строку -127,35

Код

$str60 = 'W07052 W0623 test E12727 more test second line E12725';

preg_match_all('/([EWSN])([0-9]{3})([0-9]{2})/ms', $str60, $matches);
$result60 = DMS2Decimal($degrees = (int) $matches[2][0], $minutes = (int) $matches[3][0], $seconds = 10, $direction = strtolower($matches[1][0]));


function DMS2Decimal($degrees = 0, $minutes = 0, $seconds = 0, $direction = 'n')
{
//converts DMS coordinates to decimal
//returns false on bad inputs, decimal on success

//direction must be n, s, e or w, case-insensitive
$d = strtolower($direction);
$ok = array('n', 's', 'e', 'w');

//degrees must be integer between 0 and 180
if (!is_numeric($degrees) || $degrees < 0 || $degrees > 180) {
    $decimal = false;
    //var_dump($decimal);
}
//minutes must be integer or float between 0 and 59
elseif (!is_numeric($minutes) || $minutes < 0 || $minutes > 59) {
    $decimal = false;
    //var_dump($decimal);
}
//seconds must be integer or float between 0 and 59
elseif (!is_numeric($seconds) || $seconds < 0 || $seconds > 59) {
    $decimal = false;
} elseif (!in_array($d, $ok)) {
    $decimal = false;
    //var_dump($decimal);
} else {
    //inputs clean, calculate
    $decimal = $degrees + ($minutes / 60) + ($seconds / 3600);

    //reverse for south or west coordinates; north is assumed
    if ($d == 's' || $d == 'w') {
        $decimal *= -1;
    }
}

return $decimal;
}

var_dump($matches);
var_dump($result60);

Ответы [ 2 ]

1 голос
/ 22 апреля 2019

Да, preg_replace_callback - это то, что вы хотите. Я подправил твое регулярное выражение, предполагая, что ты хочешь поймать "W0623".

Я также немного очистил вашу функцию, хотя единственным изменением в выводе было округление до 3 десятичных знаков. Остальные просто организовывали ваши условия и могут быть проигнорированы, если вы предпочитаете.

function DMS2Decimal($degrees = 0, $minutes = 0, $seconds = 0, $direction = 'n')
{
    //converts DMS coordinates to decimal
    //returns false on bad inputs, decimal on success

    $d = strtolower($direction);
    if (
        //degrees must be integer between 0 and 180
        (is_numeric($degrees) && $degrees >= 0 && $degrees <= 180) &&
        //minutes must be integer or float between 0 and 59
        (is_numeric($minutes) && $minutes >= 0 && $minutes <= 59) &&
        //seconds must be integer or float between 0 and 59
        (is_numeric($seconds) && $seconds >= 0 && $seconds <= 59) &&
        //direction must be n, s, e or w, case-insensitive
        (in_array($d, ['n', 's', 'e', 'w']))
    ) {
        $decimal = $degrees + ($minutes / 60) + ($seconds / 3600);        
        //reverse for south or west coordinates; north is assumed
        if ($d == 's' || $d == 'w') {
            $decimal *= -1;
        }
        return round($decimal, 3);
    } else {
        return false;
    }
}

$str60 = 'W07052 W0623 test E12727 more test second line E12725';
$result60 = preg_replace_callback(
    "/([EWSN])([0-9]{3})([0-9]{1,2})/ms",
    function($m) {return DMS2Decimal((int)$m[2], (int)$m[3], 10, $m[1]);},
    $str60
);
echo $result60;

Выход:

-70.869 -62.053 test 127.453 more test second line 127.419
0 голосов
/ 22 апреля 2019

Сценарий ниже может вернуть желаемый результат.Я не уверен, что дал правильные входные значения для функции, она основана на this , где NWSE - направление, следующие {2} цифры могут быть Degree, * 1006.* цифры после этого могут быть Minute, а оставшиеся цифры могут быть Second, который может быть или не быть числом с плавающей запятой.

$str60 = 'N404536 W73592.4 test E73592.4 more test second line S73592.4';
$split_strings = preg_split('/\s/s', $str60);
foreach ($split_strings as $value) {
    if (preg_match('/([EWSN][0-9\.]{4,})/ms', $value)) {
        $result60 .= DMS2Decimal(
            $degrees = (int) substr($value, 1, 2), // Not sure, this might return degrees - e.g., W{73}592.4
            $minutes = (int) substr($value, 3, 2), // Not sure, this might return minutes - e.g., W735{92}.4
            $seconds = substr($value, 5) != null ? (int) substr($value, 5) : 0, // Not sure, this checks if second is available or place zero - e.g., W7359{2.4}
            $direction = substr($value, 0, 1) // This is direction East West North South - e.g., {W}73592.4
        ) . " ";
    } else {
        $result60 .= $value . " ";
    }

}
var_dump($result60);

function DMS2Decimal($degrees = 0, $minutes = 0, $seconds = 0, $direction = 'n')
{
//converts DMS coordinates to decimal
    //returns false on bad inputs, decimal on success

//direction must be n, s, e or w, case-insensitive
    $d = strtolower($direction);
    $ok = array('n', 's', 'e', 'w');

//degrees must be integer between 0 and 180
    if (!is_numeric($degrees) || $degrees < 0 || $degrees > 180) {
        $decimal = false;
        //var_dump($decimal);
    }
//minutes must be integer or float between 0 and 59
    elseif (!is_numeric($minutes) || $minutes < 0 || $minutes > 59) {
        $decimal = false;
        //var_dump($decimal);
    }
//seconds must be integer or float between 0 and 59
    elseif (!is_numeric($seconds) || $seconds < 0 || $seconds > 59) {
        $decimal = false;
    } elseif (!in_array($d, $ok)) {
        $decimal = false;
        //var_dump($decimal);
    } else {
        //inputs clean, calculate
        $decimal = $degrees + ($minutes / 60) + ($seconds / 3600);

        //reverse for south or west coordinates; north is assumed
        if ($d == 's' || $d == 'w') {
            $decimal *= -1;
        }
    }

    return $decimal;
}

Выход

 string(56) "40.76 -73.984 test 73.984 more test second line -73.984 "
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...