Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Закрытая темаСоздание новой темы Создание опроса
> Замена рекурсии на цикл - проблема. Перебор массива. 
:(
    Опции темы
IZ@TOP
  Дата 6.1.2005, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



Есть задача, получить данные из ххх источника, пройтись циклом по этим данным как по стеку попутно проверяя эти данные на некоторое условие, если условие выполнено - взять еще данные из ххх источника и добавить полученный результат к стек-массиву.

Есть несколько вариантов, рекурсию я убрал так как после некоторого времени работы скрипта PHP вызывает ошибку переполнения стека памяти.

Первый вариант нежелателен, так как может скушать очень много памяти под массив:

Имеем массив $r в котором

Код

for($j = 0; $j < sizeof($r); $j++) {
__setx($r[$j], $info); // Функция которая принимает  данные и заносит их в базу.

if($r[$j]['ext'] != 'folder') continue; // Если условие не прошло, едем дальше.

$f->SetPath($r[$j]['path']);
$r = array_merge($r, $f->ListObjects()); // Соединяем два массива.
}


В итоге при таком раскладе у нас память засоряется массивом очень быстро. Элементов в массиве может быть очень много (от 100 до 1 000 000).

Далее смотрим второй вариант, но он не работает:

Код

while($stack = array_shift($r)) { // Здесь у нас массив с данными выступает как стек данных - то есть при каждом проходе цикла у массива $r удаляется первый эелемент и передается в переменную $stack.
__setx($stack, $info); // опять же получаем данные и пишем куда надо.
 
if($stack['ext'] != 'folder') continue; // Цикл заново.

$f->SetPath($stack['path']);
$r = array_merge($r, $f->ListObjects()); // Соединяем массивы.

$gxCounter++;
}


У второго варианта проблема в том что он по какой-то причине теряет некоторые данные.
Вот такие вот дела smile .


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
Mal Hack
Дата 6.1.2005, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 122
Всего: 261



Цитата(IZ @ 6.1.2005, 19:22)
$gxCounter++;

А это зачем?

Цитата(IZ @ 6.1.2005, 19:22)
    $f->SetPath($stack['path']);
    $r = array_merge($r, $f->ListObjects()); // Соединяем массивы.

Попробуй ради проверки:
Цитата(IZ @ 6.1.2005, 19:22)
    $f->SetPath($stack['path']);
$temp = $f->ListObjects();
    $r = array_merge($r, $temp); // Соединяем массивы.
unset($temp);


PM ICQ   Вверх
penizillin
Дата 6.1.2005, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 10.11.2004

Репутация: 8
Всего: 9



было бы лучше с примером данных, структурой $r и кодом ваших функций.
а так, наобум, можно только попробовать после каждого цикла стирать данные в ненужных переменных с помощью присваивания NULL или функции unset.

Это сообщение отредактировал(а) penizillin - 6.1.2005, 19:37
PM MAIL ICQ   Вверх
IZ@TOP
Дата 6.1.2005, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



Цитата(Mal @ 6.1.2005, 20:32)
А это зачем?

Для статистики рекурсивного обхода.

Цитата(Mal @ 6.1.2005, 20:32)
Попробуй ради проверки:

Думаю что здесь unset ненужен. Так же насколько я понял из мана, массив передается не по ссылке, но я попробую.
Добавлено @ 19:41
penizillin, думаю что структура функции __setx в данном примере не нужна, в ней только запись данных в базу. Тут и так почти вся структура приведена.
$r[0] = array('ext' => 'ext', 'path' => '/soft/');

$f->ListObjects(); возвращает массив с данными.


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
IZ@TOP
Дата 6.1.2005, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



Mal Hack, неа. не помогает. Для примера, как это дело решается рекурсией:

Код

function __getx(..., $Path) {

global $gxCounter;

$f->SetPath($Path);

if(!$r = $f->ListObjects()) return false;

$gxCounter++;

   for($j = 0; $j < sizeof($r); $j++) {
       __setx($r[$j], $info);

       if($r[$j]['ext'] == 'folder') __getx(..., $r[$j]['path']);
   }

}



--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
penizillin
Дата 6.1.2005, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 10.11.2004

Репутация: 8
Всего: 9



так может не надо записывать от 100 до 1.000.000 раз в бд одинаковые данные?
подготовьте массив, а потом его одним запросом и сохраните - а запрсы к бд (да и вообще - другим внешним сервисам) в цикле - это сильно нагружает сервер.

цикл не обязательно быстрее рекурсии, ведь она сама по себе тоже - цикл.
PM MAIL ICQ   Вверх
Mal Hack
Дата 6.1.2005, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 122
Всего: 261



Цитата(IZ @ 6.1.2005, 19:22)
if($r[$j]['ext'] != 'folder') continue;

може после
Цитата(IZ @ 6.1.2005, 19:22)
$f->SetPath($stack['path']);

Или я уже тогда алгоритм не понимаю...
PM ICQ   Вверх
IZ@TOP
Дата 6.1.2005, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



penizillin, если внимательно прочесть перый пост можно увидеть - я писал что при рекурсии PHP вызывает ошибку PHP has stack overflow. Что-то вроде переполнения стека.

И данные не одинаковые, как ты может заметил переде получением данных в скрипте устанавливается другая директория для чтения и извлечения данных.
Добавлено @ 20:01
Короче говоря, $f->SetPath($Path) устанавливает каталог для чтения, метод $f->ListObjects() читает данную директорию и возвращает ее объекты (каталоги и файлы).
Код

if($r[$j]['ext'] != 'folder') continue;

Проверка, если не каталог, прекратить, если каталог, вытащить из него объекты и добавить в стек-массив.
Добавлено @ 20:05
Все. Понял. Проблема надуманная. У меня в функции $f->ListObjects в случае неудачи возвращается false вместо массива, отсюда и проблема была.

Код теперь выглядит так:

Код
while($stack = __shift($r)) {
 __setx($stack, $info);
 
 if($stack['ext'] == 'folder') {
  $f->SetPath($stack['path']);
  $list = $f->ListObjects();
  if($list) {
   $r = array_merge($r, $list);  
   $gxCounter++;
  }
 }
}

Добавлено @ 20:06
PS Циклом быстрее получилось.


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
penizillin
Дата 6.1.2005, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 10.11.2004

Репутация: 8
Всего: 9



вы правы, я имел в виду одинаковую структуру данных.
попробуйте вынести запись в бд за пределы цикла.
PM MAIL ICQ   Вверх
IZ@TOP
Дата 6.1.2005, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



Будем считать что это идеальный вариант решщения проблемы.
Добавлено @ 20:09
penizillin, хотя запись в бд тут ни при чем, так как сервер мой и нагрузка будет раз в сутки, а то и позже. Я вот думал может писать лог в файл и потом из него читать и писать в базу?


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
penizillin
Дата 6.1.2005, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 10.11.2004

Репутация: 8
Всего: 9



можно. можно и после цикла, раз данные уже в памяти, не перекладывая их из точки А в точку Б. сформировать один запрос и отослать его в бд.
PM MAIL ICQ   Вверх
IZ@TOP
Дата 6.1.2005, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



penizillin, ты себе представляешь запрос в пару мегабайт? И как ты видишь я спецом сделал array_shift smile иначе у меня сервак зглючит. Прикнить отсканить 1ТБ фтп?


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
penizillin
Дата 6.1.2005, 20:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 10.11.2004

Репутация: 8
Всего: 9



тогда безжалостно бить запрос на макс. допустимые части. или использовать временный файл, который содержит правильно сформированые запросы, который можно скормить базе используя инструментарий системы - может дать некий прирос в скорости.
PM MAIL ICQ   Вверх
IZ@TOP
Дата 6.1.2005, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



penizillin, пока что мне приростов в скорости не нужно. Хоть он три часа будет выполнять скан. Так -как все еще зависит от скорости соединния до ФТП сервера и канала связи с ним. Задержка кстате идет очень сильная из-за ФТП, я это давно заметил.


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
Opik
Дата 6.1.2005, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: 24
Всего: 55



Цитата
Есть задача, получить данные из ххх источника, пройтись циклом по этим данным

если ты получаешь в результате массив, то проще его обработать так:
Код
function clear($one){
// твои проверки
return $result;
}
$clear = array_map("clear", $array);


Это сообщение отредактировал(а) Opr - 6.1.2005, 22:04
PM MAIL Skype   Вверх
Закрытая темаСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.6975 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.