image

Сразу к заданию или Tagliamo corto e andiamo al punto


На входе есть строка – относительный путь к файлу, например

./aa/.././bb/ccc/../../aa/some_path/file.txt

Нужно написать функцию, которая возвращает абсолютный путь к файлу и убирает все «лишние» каталоги.

Функция принимает 2 аргумента:

  • $base_dir — «текущий каталог», каталог, относительного которого задан путь к файлу
  • $relative_path — относительный путь к файлу

Например:

function getPath ($relative_path, $base_dir='/'){...}

$absolute_path = getPath('./aa/.././bb/ccc/../../aa/some_path/file.txt',
'/home/www/somesite.com/htdocs');
Var_dump($absolute_path);

Должно вернуть

string(51) "/home/www/somesite.com/htdocs/aa/some_path/file.txt"

Попытка подняться на каталог выше, чем корень / должна оставлять нас в корне /
Проверять пути и файлы на существование не нужно, функция просто трансформирует 2 исходных строки в одну.

Использовать специфичные файловые функции нельзя — надо решение на «голом» php. Функции для работы с массивами, строками, объектами можно использовать.

Моё решение


Способ 1

function getPath ($relative_path, $base_dir = '/')
{
    $base_dir = rtrim($base_dir, '/');
    $pos = strrpos($relative_path, '../');
    if ($pos !== false) {
        $relative_path = substr($relative_path, $pos + 2); // keep "/"
    }
    $relative_path = ltrim($relative_path, '/');
    return implode('/', [$base_dir, $relative_path]);
}

Способ 2 (практически то же самое)

function getPath ($relative_path, $base_dir = '/')
{
    $base_dir = rtrim($base_dir, '/');
    $pop = '';
    $pos = strrpos($relative_path, '../');
    if ($pos !== false) {
        $exp = explode('../', $relative_path);
        $pop = array_pop($exp);
    } else {
        $pop = $relative_path;
    }
    $relative_path = ltrim($pop, '/');
    return implode('/', [$base_dir, $relative_path]);
}

Ответ


n-ое задание — ни один из способов не работает корректно

Апелляция


Я, [18.06.19 16:21]
здравствуйте, так а почему не работает n-ое задание, всё же верно?

Я, [18.06.19 16:23]
получается так как и должно быть в условии

Я, [18.06.19 16:27]
«n-ое задание — ни один из способов не работает корректно» — ну как это? всё работает правильно как и в условии, можно, пожалуйста, объяснить, что не так? может для этого связаться с разработчиками, просто как было в задании — так и сделал и проверял и по ссылке вашей всё правильно

HR менеджер, [18.06.19 16:28]
Да, я уже уточняю. Вернусь к Вам с ответом как только получу фидбек

HR менеджер, [18.06.19 16:49]
[Переслано от Разработчик А]
если пройтись по строке ./aa/.././bb/ccc/../../aa/some_path/file.txt то верный ответ будет /aa/some_path/file.txt (ваш скрипт дает верный ответ)
1) ./ — Наше положение "/"
2) ./aa/ — мы заходим в аа, наше положение /aa
3) ./aa/../ — мы выходим на уровень вверх, наше положение /
4) ./aa/.././ — мы остаемся в той же папке, наше положение /
5) ./aa/.././bb/ — захоим в bb, наше положение /bb
6) ./aa/.././bb/ccc/ — заходим в ccc, наше положение /bb/ccc
7) ./aa/.././bb/ccc/../ — выходим на 1 уровень вверх, наше положение /bb
8) ./aa/.././bb/ccc/../../ — выходим на 1 уровень вверх, наше положение /
9) ./aa/.././bb/ccc/../../aa — заходим в аа, наше положение /aa
10) ./aa/.././bb/ccc/../../aa/some_path/ — захоим в папку some_path, наше положение /aa/some_path
11) ./aa/.././bb/ccc/../../aa/some_path/file.txt — добрались до файла. его полный путь /aa/some_path/file.txt

если пройтись по строке ./aa/.././bb/ccc/../some_path/file.txt то верный ответ будет /bb/some_path/file.txt (ваш скрипт дает /some_path/file.txt)
1) ./ — Наше положение "/"
2) ./aa/ — мы заходим в аа, наше положение /aa
3) ./aa/../ — мы выходим на уровень вверх, наше положение /
4) ./aa/.././ — мы остаемся в той же папке, наше положение /
5) ./aa/.././bb/ — захоим в bb, наше положение /bb
6) ./aa/.././bb/ccc/ — заходим в ccc, наше положение /bb/ccc
7) ./aa/.././bb/ccc/../ — выходим на 1 уровень вверх, наше положение /bb
8) ./aa/.././bb/ccc/../some_path/ — захоим в папку some_path, наше положение /bb/some_path
9) ./aa/.././bb/ccc/../some_path/file.txt — добрались до файла. его полный путь /bb/some_path/file.txt

Я, [18.06.19 16:52]
но по условию «Попытка подняться на каталог выше, чем корень / должна оставлять нас в корне /» — поэтому что левее "../" отбрасывается по условию

Я, [18.06.19 16:56]
это противоречит описанию прохода, кот вами скинуто, тем более что пример чётко это демонстрировал, что если есть "../" — то берётся правая часть

HR менеджер, [18.06.19 17:08]
Соискатель, похоже Вы не знаете как работает ../ в указании пути, отсюда и непонимание задачи
почитайте как работает указание пути к файлам и папкам и какую роль там играют точка(.) и две точки (..)

Я, [18.06.19 17:12]
по условию проход идёт справа, а не слева

Я, [18.06.19 17:12]
потому что «Попытка подняться на каталог выше, чем корень / должна оставлять нас в корне /»

Я, [18.06.19 17:14]
ок, не подошёл — так не подошёл, но задание просто некорректно сформулировано

HR менеджер, [18.06.19 17:17]
попытка подняться выше корня всегда оставляет в корне
вот пример
[dev_main@dev-instance-centos7 ~]$ cd /
[dev_main@dev-instance-centos7 /]$ pwd
/
[dev_main@dev-instance-centos7 /]$ cd ../
[dev_main@dev-instance-centos7 /]$ pwd
/
[dev_main@dev-instance-centos7 /]$

HR менеджер, [18.06.19 17:17]
Да, давайте останемся на связи, возможно в будущем сможем Вам предложить должность в компании

Я, [18.06.19 17:22]
так как мы находимся внутри какого-то пути, то понятие «Попытка подняться на каталог выше, чем корень / должна оставлять нас в корне /» подразумевает проход по этому пути справа налево, мы же хотим подняться из своего пути

Я, [18.06.19 17:22]
я всё равно остаюсь на своём

Я, [18.06.19 17:23]
потому что так семантически верно из условия

Я, [18.06.19 17:30]
/home/www/somesite.com/htdocs/aa/../some_path/file.txt
пытаемся подняться выше, но, учитывая «Попытка подняться на каталог выше, чем корень / должна оставлять нас в корне /» мы должны получить:
/some_path/file.txt

Я, [18.06.19 17:31]
а у вас в ответе получается чтобы подняться выше, мы должны идти сначала пути — это абсурд

Заключение


Думаю, мой подход понятен. Приведу пример:
Оживлённая трасса.
Через определённые промежутки могут быть автобусные остановки.
Если вы увидите остановку, то идите к ней.
Подход Разработчика А:
Оживлённая трасса.

Через определённые промежутки могут быть автобусные остановки.

Если вы увидите остановку, то идите в депо и пройдя все остановки, если они есть, дойдите до той остановки где вы были, но учтите, что по дороге могут встретиться ещё депо и не забывайте, что «Попытка подняться на каталог выше, чем корень / должна оставлять нас в корне /»
И ещё, зачем тогда дан пример, кот. наглядно демонстрирует мою версию условия. В любом случае, даже если только я один на свете так вижу это задание, я не считаю себя упрямым и вредным соискателем, я всего лишь отвечаю на поставленную задачу.

Так вот, добрались наконец-то. Хотелось бы увидеть комментарии, неужели только один я смотрю на эту задачу так, а она на самом деле очевидна и как говорит Разработчик А
Станислав, похоже Вы не знаете как работает ../ в указании пути, отсюда и непонимание задачи
Согласитесь, что если ждали ответа Разработчика А фраза
Попытка подняться на каталог выше, чем корень / должна оставлять нас в корне /
должна была звучать, например так
При составлении относительного пути попытка подняться на каталог выше, чем корень / должна оставлять нас в корне /
или
Попытка подняться на каталог выше, чем корень /, до самого файла, должна оставлять нас в корне /
То есть подразумевается «сначала», «слева направо». Как можно подняться на каталог выше «слева», само слово «подняться» в пути семантически подразумевает проход справа налево. Но я открыт для негативных комментариев в мой адрес, вполне может быть я просто неправильно понял условие, но ведь на то и условие, чтобы оно было однозначно в понимании всех народов всех национальностей и мировоззрения, а также влекло единственно правильное решение.

И, в заключении, невозможно подняться откуда-то, не находясь там!

Комментарии (1)


  1. edogs
    23.06.2019 19:53

    Согласны с HR «если пройтись по строке ./aa/.././bb/ccc/../some_path/file.txt то верный ответ будет /bb/some_path/file.txt „© и “Станислав, похоже Вы не знаете как работает ../ в указании пути, отсюда и непонимание задачи»©
    Уточним — в пути "./aa/.././bb/ccc/../some_path/file.txt" нет поднятия выше корня /. Первые… лишь возвращают Вас выше аа, а вторые… возвращают Вас выше ссс. Выше корня тут никто никуда не идет.

    само слово «подняться» в пути семантически подразумевает проход справа налево
    Семантически? Вы филолог что-ли? В терминах «путей» разбор пути идет всегда слева-направо, при этом можно как подниматься, так и спускаться.