Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Рекурсивная функция

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (4): [1] 2 3 4 »   

> Описание: почему то не "рекурсивица"...
Kubert
Отправлено: 24 Августа, 2011 - 14:16:57
Post Id



Частый гость


Покинул форум
Сообщений всего: 186
Дата рег-ции: Февр. 2010  


Помог: 3 раз(а)




Функция должна искать своих "предков" до корневого(т.е. со значение родителя равного "0"), записывать в массив их idObject...

Примерно картина из БД такая:
CODE (htmlphp):
скопировать код в буфер обмена
  1. id | pid | name | idObject
  2. 1 | 0 | Категория 1 | 111
  3. ...
  4. 3 | 1 | Категория 1.1 | 222
  5. ...
  6. 10 |3 | Категория 1.1.1 | 333
  7. ...
  8. 45 | 10 | Категория 1.1.1.1 | 444
  9. ...



Функция должна выводить примерно такое:
CODE (htmlphp):
скопировать код в буфер обмена
  1. $listId = array(444,333,222,111)



Массив $fintParent такого вида:
CODE (htmlphp):
скопировать код в буфер обмена
  1. $fintParent = array(
  2.     id => 1,
  3.     pid => 0,
  4.     name => Категория 1,
  5.     idObject => 111
  6. );



Сама функция
CODE (htmlphp):
скопировать код в буфер обмена
  1. function find($fintParent,$id,$listId){
  2.         $listId = array();
  3.         if($fintParent[$id]['pid'] != 0){
  4.                 $listId[] = $fintParent[$id]['pid'];
  5.                 find($fintParent,$fintParent[$id]['pid'],$listId);
  6.         }
  7.         return $listId;
  8. }
  9. print_r(find($fintParent,45));
  10.  


Где ошибка?
Сейчас заносит в массив только одного (первого) родителя...
 
 Top
Мелкий Супермодератор
Отправлено: 24 Августа, 2011 - 14:26:30
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Вы ничего не делаете со значением, которое вызывает рекурсивная функция.


-----
PostgreSQL DBA
 
 Top
Kubert
Отправлено: 24 Августа, 2011 - 14:31:52
Post Id



Частый гость


Покинул форум
Сообщений всего: 186
Дата рег-ции: Февр. 2010  


Помог: 3 раз(а)




Мелкий
Как же?
Я ищу в многомерном массиве $fintParent его родителя и добавляю в массив $listId значение $idObject
вот вроде: $listId[] = $fintParent[$id]['pid'];

Разве нет? А потом снова вызываю эту функцию но с уже id родителя и так до бесконечности пока родитель не будет равен "0"

(Отредактировано автором: 24 Августа, 2011 - 14:32:40)

 
 Top
DeepVarvar Супермодератор
Отправлено: 24 Августа, 2011 - 15:15:46
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




Kubert пишет:
родитель не будет равен "0
вот только начинать надо наоборот с нуля Закатив глазки
 
 Top
Мелкий Супермодератор
Отправлено: 24 Августа, 2011 - 15:19:19
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Kubert, не знаю, что вы там предполагаете, но в объявлении функции вы полностью игнорируете то, что вернула рекурсивная функция.


-----
PostgreSQL DBA
 
 Top
Kubert
Отправлено: 24 Августа, 2011 - 15:24:15
Post Id



Частый гость


Покинул форум
Сообщений всего: 186
Дата рег-ции: Февр. 2010  


Помог: 3 раз(а)




Мелкий
Что же она вернула и как я игнорирую это... Можете пояснить?

DeepVarvar
Мне из предыдущей функции(ее здесь нет), известен только id который я передаю в этой функции. А эта функция мне как раз помогает найти всех предков этого id...

Я явно запутался Однако
 
 Top
Мелкий Супермодератор
Отправлено: 24 Августа, 2011 - 16:52:23
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Kubert пишет:
строка 5: find($fin...

Тогда как функция результат своей работы возвращает через return. Т.о. отрабатывает зря.


-----
PostgreSQL DBA
 
 Top
Champion Супермодератор
Отправлено: 24 Августа, 2011 - 16:56:24
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




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

Kubert, ошибка в том, что измененкения, произошедшие во внутренних find() не отражаются во внешней. Нужно либо $listId передавать по ссылке, либо возвращать его и пользоваться
 
 Top
Kubert
Отправлено: 24 Августа, 2011 - 17:17:50
Post Id



Частый гость


Покинул форум
Сообщений всего: 186
Дата рег-ции: Февр. 2010  


Помог: 3 раз(а)




Champion
Не понимаю...

Мог бы ты привести код для данного примера.

Я же перед тем как вызвать внутренний find() присваиваю значение массиву...
А потом при запуске find() передаю его дальше и так пока функция не дойдет до конца.
Т.е. массив постоянно новый должен передаваться в функцию...
А когда функция закончина, то уже полностью сформированный массив передаю "ретурном".
Разве не так?
 
 Top
Champion Супермодератор
Отправлено: 24 Августа, 2011 - 18:23:53
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




Kubert пишет:
Мог бы ты привести код для данного примера.
Проще всего в объявлении функции поставить & перед последним параметром.

Kubert пишет:
Я же перед тем как вызвать внутренний find() присваиваю значение массиву...
да...
Kubert пишет:
А потом при запуске find() передаю его дальше и так пока функция не дойдет до конца.
Т.е. массив постоянно новый должен передаваться в функцию...
тоже да...
Kubert пишет:
А когда функция закончина, то уже полностью сформированный массив передаю "ретурном".
А тут нет. Полностью сформированный массив будет только внутри самой внутренней функции. Для более внешней функции массив останется без изменений. Ретурном вы его не передаете. Значение функции ничему не присваивается.
Чтоб понять что как происходит, напишите, напримеp var_dump($listId) до и после внутреннего вызова find и посмотрите, что выводит. Только не спутайте вывод того что до и того, что после, а то сделаете не те выводы
 
 Top
DeepVarvar Супермодератор
Отправлено: 24 Августа, 2011 - 18:24:06
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




Kubert я вот не понимаю зачем делать потом лишний цикл?
Ну вот сформировали мы этот промежуточный массив со всеми вложенностями.
И что дальше? При выводе еще раз перебирать с условиями?
Нафига? Перебирайте один раз - сразу в результирующую хтмл-разметку ул ли или что там будет...
(Добавление)
PHP:
скопировать код в буфер обмена
  1. function buildTree(&$arr,$parent = 0) {
  2.   $out = "";
  3.   if (is_array($arr) and count($arr) > 0) {
  4.     foreach ($arr as $item) {
  5.       if ($item['parent'] == $parent) {
  6.         $childs = buildTree($arr,$item['id']);
  7.         $out .= '<li><a href="'.$item['link'].'">'.$item['name'].'</a>'.$childs.'</li>';
  8.         }
  9.       }
  10.     }
  11.   return ($out != "") ? "<ul>$out</ul>" : "";
  12.   }
  13.  
  14. // массив вида
  15. // $arr[n]['id'] - id записи
  16. // $arr[n]['parent'] - родитель
  17. // $arr[n]['link'] - ссылка
  18. // $arr[n]['name'] - имя
  19. // учитывая что у тех кто в корне parent = 0
  20. // вызываем так
  21.  
  22. echo buildTree($arr);
 
 Top
egir
Отправлено: 24 Августа, 2011 - 23:54:28
Post Id



Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Авг. 2011  


Помог: 0 раз(а)




Реализация требуемого Вам метода, когда ф-ция возвращает массив:
PHP:
скопировать код в буфер обмена
  1.  
  2. function find($id, $listId = array())
  3. {
  4.               //Запрос к БД, чтобы достать инфу о текущей категории
  5.         $res = mysql_query("SELECT * FROM `table` WHERE (`id` = ".$id.")");
  6.         $row = mysql_fetch_array($res);
  7.  
  8.         //Помещаем ID категории в массив
  9.         $listId[] = (int)$row["id"];
  10.  
  11.         //Проверяем существует ли у данной категории родитель
  12.         if((int)$row["pid"] === 0)
  13.         {
  14.                 //Переворачиваем массив, чтобы в начале был родитель, а за ним дети [это уже по желанию]
  15.                 $listId = array_reverse($listId);
  16.                 //Возвращаем массив
  17.                 return $listId;
  18.         }
  19.         else
  20.         {
  21.                 //Ищем родителя данной категории
  22.                 find($row["pid"], $listId);
  23.         }
  24. }
  25.  
  26. //Передаем ID категории, родите которой нужно найти
  27. print_r(find(45));
  28.  


У Вас в начале ф-ции find() находился код: $listId = array(); Этого нельзя делать, вы при кадой рекурсии обнуляли массив. Код набросал на быструю руку, могут быть ошибки.

(Отредактировано автором: 25 Августа, 2011 - 00:00:10)

 
 Top
DeepVarvar Супермодератор
Отправлено: 24 Августа, 2011 - 23:59:22
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




egir пишет:
//Запрос к БД, чтобы достать инфу о текущей категории
Оооо!!!! А если их 200 или 300 ???
 
 Top
egir
Отправлено: 25 Августа, 2011 - 00:02:58
Post Id



Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Авг. 2011  


Помог: 0 раз(а)




DeepVarvar пишет:
egir пишет:
//Запрос к БД, чтобы достать инфу о текущей категории
Оооо!!!! А если их 200 или 300 ???


Ну человеку требовался именно массив. Я для таких случаев делаю таблицу, в которой содержатся все возможные связи от родителя к потомкам и потом одним запросом достаю все что мне надо. Правда при добавлении новой записи приходится переформировывать таблицу дерева связей, но лучше один раз. Хотя если в таблицах проставить индексы по айдишникам и так все будет летать.
 
 Top
DeepVarvar Супермодератор
Отправлено: 25 Августа, 2011 - 00:05:49
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




Так мой пример разбирает весь массив из одного запроса по вложеностям и ничего не нужно будет при добавлении нового пункта переформировывать.
Зачем крутить лишние циклы и запросы?
 
 Top
Страниц (4): [1] 2 3 4 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Хранение данных, их вывод и обработка »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB