Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Проблема с деревом

365
28 апреля 2005 года
MasterSID
230 / / 23.02.2003
Пытаюсь сделать вывод иерархического дерева на экран. Подскажите в чем ошибка.
Код:
array_search_key(0, 0);

$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
    $menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.4', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.5', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.6', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.7', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.8', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.9', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);

function array_search_key($parent, $lvl){
    global $menu;
    global $lvl;
    $lvl++;
    foreach($menu as $k=>$v){
        if($v['part']==$parent){
            echo "<ul>";
            echo "";
            echo $v['name'];
            echo "";
            array_search_key($k, $lvl);
            $lvl--;
            echo "[/list]";
        }
    }
}
287
28 апреля 2005 года
Shiizoo
958 / / 14.03.2004
omg=) ты вызываешь функцию до создания массива ^^ вроде бы интерпертатор пхп проходит весь код до конца перед его выполнением, но далее все идет в соответствии с логикой - сначало первое, потом второе...;)

де, точняк. ошибка лезет на стадии выполнения;) гм, надо бы разобраться в механизме работы зендомашины или что там в нем. глядишь кодинг эффективнее станет ^^
365
28 апреля 2005 года
MasterSID
230 / / 23.02.2003
Самое интересное, что если не делать рекурсии т.е. убрать эту функцию, то все работает по порядку.
287
28 апреля 2005 года
Shiizoo
958 / / 14.03.2004
Непонял=))) Работа идет сверху вниз:
1. вызов array_search_key(0,0)
2. в теле функции вызывается foreach цикл и бьется на том, что $menu есть null.

А нужно чтобы было:
1.объявление $menu
2.вызов array_search_key(0,0)
...
и т.п.

Куда ты втыкнешь само тело функции неважно (переходя с perl' а мне эта штука очень понравилась ^^). Суть в том где находится ее вызов:)ъ
365
29 апреля 2005 года
MasterSID
230 / / 23.02.2003
Да нет, это я просто когда в попыхах собирал обрывки кода в этот кусок перепутал местами. В программе все как надо идет, эти 3 блока просто в разных файлах:
Код:
$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
    $menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
    $menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);


function array_search_key($parent, $lvl){
    global $menu;
    global $lvl;
    $lvl++;
    foreach($menu as $k=>$v){
        if($v['part']==$parent){
            echo "<ul>";
            echo "";
            echo $v['name'];
            echo "";
            array_search_key($k, $lvl);
            $lvl--;
            echo "[/list]";
        }
    }
}
array_search_key(0, 0);

А вот результат:
 
Код:
Раздел 1
    Раздел 1.1



А должно быть:
 
Код:
Раздел 1
    Раздел 1.1
    Раздел 1.2
    Раздел 1.3
Раздел 2


Теперь, если исключить вызов array_search_key из самой себя, то foreach вернет все нужные значеничения, кроме вложеных конечно. В чем тут соль?
287
29 апреля 2005 года
Shiizoo
958 / / 14.03.2004
Код:
<?php

$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);

function array_search_key($p,$l)
{
    global $menu;

    $str = <<<EOF
<ul>
        %s
    [/list]EOF;

    reset($menu);

    while (list($k,) = each($menu))
    {
        if ($menu[$k]['part'] == $p)
        {
            printf($str,$menu[$k]['name']);
            $pos = pos($menu);
            array_search_key($k,$l+1);
            array_seek($menu,$pos);
        }
    }
}

function array_seek(&$array, $pos)
{
    reset($array);

    $cpos = current($array);

    while ($cpos !== false && $cpos != $pos)
    {
        $cpos = next($array);
    }

    return $cpos;
}

array_search_key(0,0);

?>


Соль в том, что foreach сбрасывает при инициализации внутр. указатель массива, а далее юзает его таким какой он есть, невзирая на то, каким он был на момент последней итерации. А это значит, что с ним рекурсия без особых заморочек не получится.

Вот другой вариант:

Код:
<?php

$menu[1]=array('name'=>'Раздел 1', 'URL'=>'', 'part'=>0);
$menu[]=array('name'=>'Раздел 1.1', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.2', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 1.3', 'URL'=>'', 'part'=>1);
$menu[]=array('name'=>'Раздел 2', 'URL'=>'', 'part'=>0);

function array_search_key($p,$l)
{
    global $menu;

    $str = <<<EOF
<ul>
        %s
    [/list]EOF;



    foreach (array_keys($menu) as $k)
    {
        if ($menu[$k]['part'] == $p)
        {
            printf($str,$menu[$k]['name']);
            array_search_key($k,$l+1);
        }
    }
}

array_search_key(0,0);

?>


Правда сейчас я врдли соображу что экономнее;) Разница тут очевидна, а почему работает без дополнительного контроля над указателем массива счас объясню. На инициализации foreach'а создается анонимный (в perl'е так было, думаю и в php реализация не особо отличается) массив ключей массива $menu, чьим указателем и рулит данный foreach. Когда дело доходит до рекурсии, то все идет по той же схеме, и foreach'и в данном случае юзает не один единственный массив и дружно перемещают указатель то влево, то вправо, а каждый работает со своим собственным экземпляром. Единственный минус который пришел в голову это накладные расходы для хранения этих анонимов, так что тут все зависит от объема этого самого $menu.

фсё, сплу
365
01 мая 2005 года
MasterSID
230 / / 23.02.2003
Все понял, спасибо!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог