Создать ассоциативный массив с ключами, например, из URL [решено]

dimases

Новичок
Часто сталкивался с такой задачей, но решал ее всегда как-то иначе, так как решения не находил, но одно должно быть.
Есть несколько урлов (string):
/data/images/
/ru/nashi_kontakti/
/ru/remont_stiralnih_mashin/
/ru/remont_stiralnih_mashin/aeg/
/ru/faq/

Нужно создать ассоциативный массив:
PHP:
array(
   "data" => array(
       "images" => true,
   ),
   "ru" => array(
       "nashi_kontakti" => true,
       "remont_stiralnih_mashin" => array(
           "aeg" => true,
       ),
       "faq" => true,
   ),
);
То есть, explode("/",$string)... А вот как дальше? Как адресовать?
 

dimases

Новичок
Не, ей там делать нечего, приятель подсказал решение:
PHP:
                $urls = [
                        '/data/images/',
                        '/ru/nashi_kontakti/',
                        '/ru/remont_stiralnih_mashin/',
                        '/ru/remont_stiralnih_mashin/aeg/',
                        '/ru/remont_stiralnih_mashin/beg/',
                        '/ru/faq/'
                ];
                $result = [];
                foreach ($urls as $url) {
                        $parts = array_values(array_filter(explode('/', trim($url))));
                        $length = count($parts);
                        $res = true;
                        for($i = $length - 1; $i >= 0; $i--) {
                                $buffer = [$parts[$i] => $res];
                                $res = $buffer;
                        }
                        $result = array_replace_recursive($result, $buffer);
                }
                var_dump($result);
 

WMix

герр M:)ller
Партнер клуба
@fixxxer, тоже самое что и ты написал :)

@dimases, без "true" на концах
PHP:
$urls = [
    '/data/images/',
    '/ru/nashi_kontakti/',
    '/ru/remont_stiralnih_mashin/',
    '/ru/remont_stiralnih_mashin/aeg/',
    '/ru/remont_stiralnih_mashin/beg/',
    '/ru/faq/'
];
$result = [];
foreach ($urls as $url) {
    $temp = &$result;
    foreach(explode('/',trim($url, '/')) as $part){
        $temp = &$temp[$part];
    }
}
print_r($result);
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
В данном случае рекурсивная функция уже написана внутри array_replace_recursive.

Но, разумеется, общеизвестно, что любой рекурсивный алгоритм можно переписать без рекурсии, в виде циклов. Например, так:

PHP:
$urls = [
    '/data/images/',
    '/ru/nashi_kontakti/',
    '/ru/remont_stiralnih_mashin/',
    '/ru/remont_stiralnih_mashin/aeg/',
    '/ru/faq/',
];

function deepAssign(array &$a, array $path, $value) {
    $lastToken = array_pop($path);
    if ($lastToken === null) {
        return;
    }
    while (null !== $token = array_shift($path)) {
        if (!isset($a[$token]) || !is_array($a[$token])) {
            $a[$token] = [];
        }
        $a = &$a[$token];
    }
    $a[$lastToken] = $value;
}

$result = [];
foreach ($urls as $url) {
    deepAssign($result, explode('/', trim($url, '/')), true);
}


assert($result == array(
   "data" => array(
       "images" => true,
   ),
   "ru" => array(
       "nashi_kontakti" => true,
       "remont_stiralnih_mashin" => array(
           "aeg" => true,
       ),
       "faq" => true,
   ),
));
 

Yoskaldyr

"Спамер"
Партнер клуба
Правда рекурсия чаще бывает значительно короче
 

fixxxer

К.О.
Партнер клуба
Правда рекурсия чаще бывает значительно короче
Ну и я бы сказал, что можно разделить "итеративные" алгоритмы на две категории
1) честная переработка на циклы и указатели, но это не всегда возможно
2) вручную управляемый стек, то есть по сути та же рекурсия в смысле возможного переполнения стека, скажем, нерекурсивный QuickSort без стека и не сделаешь.

Во втором случае вообще особого смысла нет, разве что решить таким образом проблемы с конкретными реализациями компиляторов/vm, где рекурсия получается дорогая.
 

fixxxer

К.О.
Партнер клуба
Кто ж запрещает? Смотри.

UPD: php_error_docref(NULL, E_WARNING, "recursion detected"); там выглядит забавно. Понятно, конечно, что речь про бесконечную... Но забавно :)
 
Сверху