Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Рекурсия при обработке массива
 
 автор: neudor   (18.09.2006 в 14:35)   письмо автору
 
 

Прошу прощения у господ админов. Но мне кажется что перенесённая вами тема относится к разделу PHP. Я немного изменил вопрос, чтобы соответствовать разделу. Так что ту тему можно удалить. http://www.softtime.ru/forum/read.php?id_forum=3&id_theme=24716

Так вот.
Имеем древовидное меню, записанное в массив. Нудно его вывести, соблюдая уровни.Применим рекурсию.
<?php
//исходный массив
//children - bool - есть ли у элемента потомки
//parent - int - кто родитель элемента
$array = Array(
    
"1" => array("title" => "menu1""children" => "0""parent" => "0"),
    
"2" => array("title" => "menu2""children" => "1""parent" => "0"),
    
"3" => array("title" => "menu2.1""children" => "0""parent" => "2"),
    
"4" => array("title" => "menu2.2""children" => "1""parent" => "2"),
    
"5" => array("title" => "menu2.2.1""children" => "0""parent" => "4"),
    
"6" => array("title" => "menu2.2.2""children" => "0""parent" => "4"),
    
"7" => array("title" => "menu2.2.3""children" => "0""parent" => "4"),
    
"8" => array("title" => "menu2.3""children" => "0""parent" => "2"),
    
"9" => array("title" => "menu2.4""children" => "0""parent" => "2"),
    
"10" => array("title" => "menu3""children" => "0""parent" => "0"),
    
"11" => array("title" => "menu4""children" => "0""parent" => "0")
);

function 
tree($parent=0$level=1) {
    global 
$array;  
    
    foreach(
$array as $id=>$values) {
        
//если родитель текущего элемента не равен искомому, пропускаем его.
        
if($values['parent']!=$parent) continue;
        
        
//формирование префикса и вывод. (смотрите ниже)
        
$prefix=""; for($i=0$i<$level$i++) $prefix.="--";
        echo 
"$prefix$values[title]<br>";
        
        
//если у текущего элемента есть потомки, рекурсируем
        
if($values['children']!=0)
            
tree($id$level+1);        
    }
}

$arr tree();
?>

Эта штука выводит
--menu1
--menu2
----menu2.1
----menu2.2
------menu2.2.1
------menu2.2.2
------menu2.2.3

Это не есть то что нужно.
Нужно вот что:
--menu1
--menu2
----menu2_1
----menu2_2
------menu2_2_1
------menu2_2_2
------menu2_2_3
----menu2_3
----menu2_4
--menu3
--menu4

как нам получить такой вывод?
у меня заработало вот так:
<?php
function tree($parent=0$level=1) {
    
$array = Array(
        
"1" => array("title" => "menu1""children" => "0""parent" => "0"),
        
"2" => array("title" => "menu2""children" => "1""parent" => "0"),
        
"3" => array("title" => "menu2_1""children" => "0""parent" => "2"),
        
"4" => array("title" => "menu2_2""children" => "1""parent" => "2"),
        
"5" => array("title" => "menu2_2_1""children" => "0""parent" => "4"),
        
"6" => array("title" => "menu2_2_2""children" => "0""parent" => "4"),
        
"7" => array("title" => "menu2_2_3""children" => "0""parent" => "4"),
        
"8" => array("title" => "menu2_3""children" => "0""parent" => "2"),
        
"9" => array("title" => "menu2_4""children" => "0""parent" => "2"),
        
"10" => array("title" => "menu3""children" => "0""parent" => "0"),
        
"11" => array("title" => "menu4""children" => "0""parent" => "0")
    );

    foreach(
$array as $id=>$values) {
        if(
$values['parent']!=$parent) continue;
        
        
$prefix=""; for($i=0$i<$level$i++) $prefix.="--";
        echo 
"$prefix$values[title]<br>";
        
        if(
$values['children']!=0)
            
tree($id$level+1);
    }    
}

tree();
?>

Практически ничего не изменилось. Просто определение исходного массива засунуто в саму функцию. Так всё работает

А в первом варианте рекурсивно вызванные функции, как я понял, не передают управление вызвавшей, а просто самая "нижняя" из них при достижении конца завершает работу всей конструкции.

Кто-нибудь знает, что происходит?

   
 
 автор: Wita1y   (18.09.2006 в 18:18)   письмо автору
 
   для: neudor   (18.09.2006 в 14:35)
 

>echo "$prefix$values[title]<br>";
1. А где написано что переменные можно записывать таким образом?
2. И еще мне казалось что все то что находиться в квадратных скобках должно быть заключены в кавычках. Или можно и так?

   
 
 автор: kasmanaft   (18.09.2006 в 20:20)   письмо автору
 
   для: Wita1y   (18.09.2006 в 18:18)
 

1) В смысле? Можно записывать в кавычках ... только в двойных
2) То что в кв. скобках должно быть строкой ... оно итак строка, кавычки просто не там стоят

   
 
 автор: Wita1y   (18.09.2006 в 20:24)   письмо автору
 
   для: kasmanaft   (18.09.2006 в 20:20)
 

>В смысле? Можно записывать в кавычках ... только в двойных
В смысле что переменные вместе соединены $a$b

   
 
 автор: neudor   (19.09.2006 в 06:48)   письмо автору
 
   для: Wita1y   (18.09.2006 в 20:24)
 

Wita1y
Если вы запишите
<?php
echo "$values['title']"//1
echo $values[title]; //2
?>

то получите ошибку
Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING //1

и для второй строчки
Notice: Use of undefined constant title - assumed 'title' //2

Правильно вот так:
<?php
echo "$values[title]"//1
echo $values['title']; //2
?>


По поводу "соединённых" переменных.
ошибочная констукция:
<?php
echo $prefix$values['title'];
?>

Parse error: syntax error, unexpected T_VARIABLE, expecting ',' or ';'

А вот если вы запишите всё в двойных кавычках, умный PHP просто выведет переменные одну за другой без пробелов.
<?php
echo "$prefix$values[title]";
?>

   
 
 автор: Wita1y   (19.09.2006 в 14:42)   письмо автору
 
   для: neudor   (19.09.2006 в 06:48)
 

В книги по которой я учусь такого нет(может плохо читал), но есть форум.
Большое спасибо вам. Буду знать! :-)

   
 
 автор: kasmanaft   (18.09.2006 в 20:17)   письмо автору
 
   для: neudor   (18.09.2006 в 14:35)
 

думаю дело вот в чем:


Ссылки с глобальными и статическими переменными

Движок Zend 1, лежащий в основе PHP 4, оперирует модификаторами переменных static и 
global как ссылками. Например, реальная глобальная переменная, внедренная в область
 видимости функции указанием ключевого слова global, в действительности создает ссылку
 на глобальную переменную. Это может привести к неожиданному поведению.

Аналогично ведет себя и выражение static. Ссылки не хранятся статично.

(код)

Этот пример демонстрирует, что при присвоении ссылки статической переменной она не
 запоминается, когда вы вызываете функцию &get_instance_ref() во второй раз.
http://php.net/ru/global

Можно использовать $array = $GLOBALS['array']; тогда тоже будет работать

   
 
 автор: neudor   (19.09.2006 в 06:34)   письмо автору
 
   для: kasmanaft   (18.09.2006 в 20:17)
 

Решил проблему ещё вчера. Сделал немного "через одно место", но тоже заработало.
<?php
function tree($parent=0$level=1) {
    global 
$array;
    
$ret = Array();
    
$found = Array();

    
$prefix=""; for($i=0$i<$level$i++) $prefix.="--";
    
    foreach(
$array as $id=>$values) {
        if(
$values['parent']!=$parent) continue;
        
$found[serialize($values)]=$id;
    }
    
    foreach(
$found as $seria=>$id) {
        
$values unserialize($seria);
        
$val "$prefix$values[title]";
        
        if(
$values['children']!=0
            
$ret[$val] = tree($id$level+1);
        else 
            
$ret[$val] = 1;
    }
    
ksort($ret);
    return 
$ret;
}
$arr=tree();
echo 
"<pre>"print_r($arr); echo "</pre>";
?>

На вывод получил:
Array
(
    [--menu1] => 1
    [--menu2] => Array
        (
            [----menu2.1] => 1
            [----menu2.2] => Array
                (
                    [------menu2.2.1] => 1
                    [------menu2.2.2] => 1
                    [------menu2.2.3] => 1
                )

            [----menu2.3] => 1
            [----menu2.4] => 1
        )

    [--menu3] => 1
    [--menu4] => 1
)

это уже можно разобрать через array_walk_recursive().

kasmanaft большое спасибо за ваше решение! Работает. Теперь буду выбирать!

   
 
 автор: Wita1y   (19.09.2006 в 10:23)   письмо автору
 
   для: neudor   (18.09.2006 в 14:35)
 

Я тут сейчас снова за рекурсии взялся. Понял как оно работает на таком уровне:

<?
  
function degree($x,$y)
  {
    if(
$y)
    {
      return 
$x*degree($x,$y-1);
    }
    return 
1;
  }
  echo(
degree(2,4)); // выводит 16
?>


А у вас рекурсия где находиться? Ведь называете вы тему: "Рекурсия при обработке массива", т.е. рекурсивное вычисление факториала при обработке массива. Или я опять что-то путаю!?
neudor, покажите пожалуйста, где начинается рекурсивное вычисление. Если можно, то во втором случае, когда обработка массива находится внутри функции (тела) а не за функцией как в самом начале темы.

   
 
 автор: neudor   (19.09.2006 в 13:16)   письмо автору
 
   для: Wita1y   (19.09.2006 в 10:23)
 

Wita1y

Рекурсия - это вызов функцией самой себя. Вот и ищите в теле вызов функции с таким же названием.

Подскажу:
<?php
if($values['children']!=0
            
tree($id$level+1);
?>

Комментарии читайте к самому первому скрипту - там всё то же самое.

   
 
 автор: Wita1y   (19.09.2006 в 14:34)   письмо автору
 
   для: neudor   (19.09.2006 в 13:16)
 

Беру свои слова обратно. :-)

>автор: Wita1y (19.09.2006 в 10:23) письмо автору
>Я тут сейчас снова за рекурсии взялся. Понял как оно работает на таком уровне:

>А у вас рекурсия где находиться? Ведь называете вы тему:
>"Рекурсия при обработке массива", т.е. рекурсивное вычисление
>факториала при обработке массива. Или я опять что-то путаю!?
>neudor, покажите пожалуйста, где начинается
>рекурсивное вычисление. Если можно, то во втором случае,
>когда обработка массива находится внутри функции (тела)
>а не за функцией как в самом начале темы.

Я смотрю в код и не вижу комментариев. :-)))
Как бы устно пытаюсь разобрать ваш код, что из чего выходит. Настолько сильное внимание у меня на структура кода что даже не замечаю комментариев. Ну да ладно, с кем не бывает.

Или все такие внимательные здесь?! :-)

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования