[AI CS4-CS6] Рекурсия в цикле

Статус
Закрыто для дальнейших ответов.

Bigroom

Участник
Топикстартер
Сообщения
26
Реакции
3
Добрый вечер. Столкнулся с проблемой и не могу разобраться. Быть может я просто не сильно разбираюсь в JavaScript, надеюсь вы подскажете в чем дело.

Пишу скрипт, который удаляет все контуры за пределами квадрата (0; 0; 320; 320). Для этого мне нужно пройтись по всей древовидной структуре групп. Для этого написал функцию, в которой содержится цикл, в котором опять эта функция должна вызываться рекурсивно. Но оно у меня не работает: функция рекурсивно вызывается, но после этого следующая итерация цикла не наступает. Почему ?

Код:
sel = activeDocument.selection;

delItems = [];

function geatherP (group){

pItems = group.pathItems;
cpItems = group.compoundPathItems;
gItems = group.groupItems;

if (pItems){
for (i=0; i < pItems.length; i++){
if (pItems[i].locked == true || pItems[i].hidden == true) continue;
b = pItems[i].geometricBounds;
if (b[0] >= 0 && b[1] <=0 && b[2] <= 320 && b[3] >= -320) continue;
delItems.push (pItems[i]);
}
}

if (cpItems){
for (i=0; i < cpItems.length; i++){
if (cpItems[i].locked == true || cpItems[i].hidden == true) continue;
b = cpItems[i].geometricBounds;
if (b[0] >= 0 && b[1] <=0 && b[2] <= 320 && b[3] >= -320) continue;
delItems.push (cpItems[i]);
}
}

if (gItems){
for (i=0; i < gItems.length; i++){                                        //проблемный блок
if (gItems[i].locked == true || gItems[i].hidden == true) continue;
geatherP (gItems[i]);
}
}
}

for (i=0; i < sel.length; i++){
if (sel[i].locked == false && sel[i].hidden == false){
if (sel[i].typename == 'PathItem' || sel[i].typename == 'CompoundPathItem'){
delItems.push (sel[i]);
continue;
} else if (sel[i].typename == 'GroupItem') geatherP (sel[i]);
}
}

for (i=0; i < delItems.length; i++) delItems[i].remove();
 

splxgf

12 лет на форуме
Сообщения
7 744
Реакции
3 425
Если уж удаляете элементы, то перебор лучше делать в обратном порядке.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 235
Реакции
10 852
А вы уверены, что переменные i у вас в процедуре и в основной программе различные? Кроме того, нужно приучаться все операции сравнения, разделенные логическими операциями в скобки брать. Это так, капитанские соображения по поводу.
 
  • Спасибо
Реакции: Bigroom

splxgf

12 лет на форуме
Сообщения
7 744
Реакции
3 425
Ну в коде же видно, что сначала я собираю базу элементов, а потом уже удаляю их в отдельном цикле
Вы хотите удалить их все или производить выборочное удаление?
К примеру берете третий элемент, под условие он подходит и удаляется... при этом индексы будут смещены, а вы на следующей итерации проверять будете четвертый элемент (который ранее был пятым, а четвертый проверка не затронет).
При неполном удалении у вас глубина рекурсии может превышать допустимые пределы.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 235
Реакции
10 852
Вы хотите удалить их все или производить выборочное удаление?
К примеру берете третий элемент, под условие он подходит и удаляется... при этом индексы будут смещены, а вы на следующей итерации проверять будете четвертый элемент (который ранее был пятым, а четвертый проверка не затронет).
При неполном удалении у вас глубина рекурсии может превышать допустимые пределы.
Да нет, дело не в этом - там коллекция накапливается из удаляемых элементов, ееэлементы можно в произвольном порядке удалять, поскольку в ней обьекты содержатся а не ссылки на элементы списка. Мне кажется самой правдоподобной причиной - отсутствие локальных переменных, свойственное программистам одной большой и древней страны.
 

Skvoznyak

15 лет на форуме
Сообщения
5 500
Реакции
2 168
i тут глобальная получается, да. как и все остальные переменные до кучи, я вообще не понимаю как это работает )
 

splxgf

12 лет на форуме
Сообщения
7 744
Реакции
3 425
Ну в коде же видно, что сначала я собираю базу элементов, а потом уже удаляю их в отдельном цикле
хотя да, не увидел что они предварительно собираются.
Ну тогда либо переменная цикла пересекается, либо завести счетчик рекурсивных вызовов и выводить его.
 

Bigroom

Участник
Топикстартер
Сообщения
26
Реакции
3
А вы уверены, что переменные i у вас в процедуре и в основной программе различные? Кроме того, нужно приучаться все операции сравнения, разделенные логическими операциями в скобки брать. Это так, капитанские соображения по поводу.
С "i" там все как обычно. Начальное значение ей присваивается на старте каждого цикла. Я как дилетант могу предположить, что "i" меняет свое значение после рекурсии, но тут уж ничего нельзя поделать - на то она и рекурсия. Хотя, можно попробовать сделать так:
Код:
if (gItems){
for (i=0; i < gItems.length; i++){                                        //проблемный блок
if (gItems[i].locked == true || gItems[i].hidden == true) continue;
a = i;
geatherP (gItems[i]);
i = a;
}
}
Типа записать "i" в буферную переменную "a". Сейчас попробую.
 

splxgf

12 лет на форуме
Сообщения
7 744
Реакции
3 425
Я как дилетант могу предположить, что "i" меняет свое значение после рекурсии, но тут уж ничего нельзя поделать - на то она и рекурсия.
У вас одна глобальная переменная i, либо имя ей изменить в function geatherP, либо объявить через var чтобы она не пересекалась с глобальной.
 
  • Спасибо
Реакции: Bigroom

Skvoznyak

15 лет на форуме
Сообщения
5 500
Реакции
2 168
что значит ничего не поделать? ее нужно объявить локальной везде


for (var i=0; i < gItems.length; i++)

и так далее


иначе ваша функция как только вы ее вызываете первый раз в цикле меняет значение i на какое-то неизвестное нам, и цикл уже нарушается

то же самое происходит с

pItems = group.pathItems;
cpItems = group.compoundPathItems;
gItems = group.groupItems;


везде добавьте var перед объявлением, тогда переменная будет локальной для функции/цикла. это же самые азы
 
  • Спасибо
Реакции: Flame и Bigroom

Bigroom

Участник
Топикстартер
Сообщения
26
Реакции
3
Я и не знал о таких фишках, думал что "var i = 0" эквивалентно "i = 0". Но проблема осталась: поставил везде var, однако то же самое.

И моя затея с "a" не сработает, "a" ведь тоже будет во время рекурсии меняться.
 

splxgf

12 лет на форуме
Сообщения
7 744
Реакции
3 425
А файл для примера можно?
 

Bigroom

Участник
Топикстартер
Сообщения
26
Реакции
3
Я добавил еще побольше "варов", и все заработало! 'dans))'хз каким образом. Спасибо за помощь! Буду знать: в любой непонятной ситуации надо ставить "вары"

Если конкретно, то в данном случае "var" надо было поставить здесь: var gItems = group.groupItems;



Не по теме:
кстати, а сколько же будет 0.2 + 0.1 ?
 
Последнее редактирование:
  • Спасибо
Реакции: splxgf

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 235
Реакции
10 852
Я добавил еще побольше "варов", и все заработало! 'dans))'хз каким образом. Спасибо за помощь! Буду знать: в любой непонятной ситуации надо ставить "вары"
Все ругают современный софт, тормозной, прожорливый и глючный. А я думаю, одна из причин - современные программисты из юговосточной Азии развращены отсутствием обязательного объявления типизированных переменных во всевозможных интерпретируемых языках. Я понять не могу, неужели, когда вы используете переменные с одними и теми же именами в разных местах программы, Кэп ни на секунду не отвлекает вас мыслью, что у этих переменных, вообще-то, уже значение есть и оно в этот момент портится безвозвратно? Не надо ставить бездумно вары - хотя бы называйте переменные по разному. Путаетесь с переменными? - тогда приучайтесь к аккуратности - в начале каждой процедуры объявляйте через var все используемые в ней переменные. Про выражения в скобках я уже говорил выше. И тогда будете ограждены от подобных ситуаций.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 235
Реакции
10 852

Не по теме:
Объяснение там, кстати, совершенно дурацкое, более того, с их точки зрения, как раз, в javascript 0.1+0.2=0.3
Попробуйте alert("0.1+0.2=",0.1+0.2) и сами убедитесь
В жабаскрипте гораздо более отмороженная фишка есть, про которую мало кто упоминает, попробуйте alert(111111111111111111111) - будете весьма удивлены ;)

 
Статус
Закрыто для дальнейших ответов.