|
Рекурсия зацикливается | ☑ | ||
---|---|---|---|---|
0
dGU
31.01.12
✎
16:15
|
Процедура КнопкаВыполнитьНажатие(Кнопка)
Объект = ТребованиеНакладная.ПолучитьОбъект(); Движение = Объет.Движения.Хозрасчетный; Движение.Прочитать(); Хозрасчетный = Движение.Выгрузить(); Проверить(Хозрасчетный, Хозрасчетный.Скопировать()) КонецПроцедуры Процедура Проверить(Хозрасчетный, Хозрасчетный1) Для Каждого Стр Из Хозрасчетный Цикл НайденнаяСтрока = Хозрасчетный1.Найти(Стр.СчетДт, "СчетДт"); Если НайденнаяСтрока <> Неопределено Тогда Хозрасчетный .Удалить(Стр); Хозрасчетный1.Удалить(НайденнаяСтрока); ПроверитьРегистры(Хозрасчетный, Хозрасчетный1); КонецЕсли; КонецЦикла; Если ТаблицаДвиженийРегистров.Количество() = 0 И ТаблицаДвиженийРегистровКОМОбъект.Количество() = 0 Тогда Сообщить("1"); КонецЕсли; КонецПроцедуры Выше приведен пример обработки, которая "зацикливает рекурсию", по непонятной причине. После выхода из цикла и вывода сообщения, снова запускается процедура. В чем подвох? |
|||
1
Alex S D
31.01.12
✎
16:15
|
ПроверитьРегистры а это че такое
|
|||
2
DmitrO
31.01.12
✎
16:16
|
Когда перебираешь коллекцию циклом Для каждого нельзя изменять ее состав.
|
|||
3
Guk
31.01.12
✎
16:16
|
а выход из рекурсии Пушкин делать будет?...
|
|||
4
Guk
31.01.12
✎
16:19
|
кстати, в приведенном коде рекурсии не обнаружено...
|
|||
5
Reset
31.01.12
✎
16:20
|
А где здесь рекурсия? И что за "ПроверитьРегистры"?
|
|||
6
dGU
31.01.12
✎
16:32
|
Пардон код следующий:
(3) Выход из рекурсии происходит когда не выполняется условие "Если..." Процедура КнопкаВыполнитьНажатие(Кнопка) Объект = ТребованиеНакладная.ПолучитьОбъект(); Движение = Объет.Движения.Хозрасчетный; Движение.Прочитать(); Хозрасчетный = Движение.Выгрузить(); Проверить(Хозрасчетный, Хозрасчетный.Скопировать()) КонецПроцедуры Процедура Проверить(Хозрасчетный, Хозрасчетный1) Для Каждого Стр Из Хозрасчетный Цикл НайденнаяСтрока = Хозрасчетный1.Найти(Стр.СчетДт, "СчетДт"); Если НайденнаяСтрока <> Неопределено Тогда Хозрасчетный .Удалить(Стр); Хозрасчетный1.Удалить(НайденнаяСтрока); Проверить(Хозрасчетный, Хозрасчетный1); КонецЕсли; КонецЦикла; Если ТаблицаДвиженийРегистров.Количество() = 0 И ТаблицаДвиженийРегистровКОМОбъект.Количество() = 0 Тогда Сообщить("1"); КонецЕсли; КонецПроцедуры |
|||
7
hhhh
31.01.12
✎
16:38
|
(6) движения хочешь почистить. Втот так тогда
Процедура КнопкаВыполнитьНажатие(Кнопка) Объект = ТребованиеНакладная.ПолучитьОбъект(); Движение = Объект.Движения.Хозрасчетный; Движение.Прочитать(); Хозрасчетный = Движение.Выгрузить(); Хозрасчетный.Очистить(); КонецПроцедуры то же самое получится. |
|||
8
Rie
31.01.12
✎
16:41
|
(6) Удалять внутри такой итерации - несколько неизящно, IMHO.
Да и, не закончив работу одного итератора, запускать на том же объекте ещё один, затем ещё и ещё... Тем паче, что рекурсия тут несколько неестественно смотрится. |
|||
9
dGU
31.01.12
✎
16:41
|
:) спасибо, за ответ но вопрос актуален.
Если прогнать обработку в отладчике, после того как обе таблицы очищены выводиться сообщение. Затем заново запускается процедура. |
|||
10
kosts
31.01.12
✎
16:43
|
(6) Код полностью переписать.
Рекурсия совершенно не нужна. Удаление элементов в коллекции в цикле по этой же коллекции - результат не предсказуем. думаю можно так сделать (грубо).
|
|||
11
dGU
31.01.12
✎
16:46
|
Спасибо, такой вариант конечно рассматривался, просто интересно почему рекурсия так работает, точнее вызывается уже после выхода из цикла.
|
|||
12
Rie
31.01.12
✎
16:47
|
(9) Обе таблицы очищены у тебя на самой-самой большой глубине рекурсии. Потом ты выходишь из _последнего_ вызова и - опаньки! - возвращаешься в предыдущий. Который продолжает свой цикл как ни в чём ни бывало. И т.д.
|
|||
13
kosts
31.01.12
✎
16:48
|
(11) Может "прервать" не хватает...
|
|||
14
Ненавижу 1С
гуру
31.01.12
✎
16:49
|
еще раз танкисту:
Для Каждого Стр Из Хозрасчетный Цикл ... Хозрасчетный .Удалить(Стр); //Ошибка: При обходе коллекции "Для каждого" коллекцию изменять нельзя! ... КонецЦикла; |
|||
15
Rie
31.01.12
✎
16:49
|
(11) Выгрузи свои наборы записей в таблицы значений, сделай с ними всё, что требуется (по человечески, без ненужной рекурсии в циклах с модицифируемым объектом итерации), загрузи обратно наборы записей - и будет счастье.
|
|||
16
Ненавижу 1С
гуру
31.01.12
✎
16:49
|
(10) ипануться
|
|||
17
kosts
31.01.12
✎
16:51
|
(16) И не говори... :-)
|
|||
18
Reset
31.01.12
✎
16:51
|
(10) Приведенный код замечателен тем, что несовпадающие строки (для надежности!) ищутся по нескольку раз. Наглядное, правильное решение, удачно можно использовать в холиварах про goto.
|
|||
19
dGU
31.01.12
✎
16:51
|
(15) Спасибо вроде бы я понял, но (16) почему //Ошибка: При обходе коллекции "Для каждого" коллекцию изменять нельзя,почему нельзя менять-то?
|
|||
20
GROOVY
31.01.12
✎
16:53
|
(19) Итератор с ума сходит просто.
|
|||
21
Ненавижу 1С
гуру
31.01.12
✎
16:55
|
(19) потому что это плохо и НЕ православно, более того в C# даже будет ран-тайм, 1С просто было лень делать такие проверки
|
|||
22
Rie
31.01.12
✎
16:55
|
(19) Не знаю, как писали итератор авторы 1С 8.2, но они явно не предполагали такого его использования и не перестраховались на случай подобных извратов.
|
|||
23
napagokc
31.01.12
✎
16:56
|
Объект = ТребованиеНакладная.ПолучитьОбъект();
Движение = Объет.Движения.Хозрасчетный; во второй строчке опечатка или так и задумано "Объет"? (пропущена буква "к") |
|||
24
dGU
31.01.12
✎
16:57
|
задумано чтобы всех ввести в заблуждение
|
|||
25
kosts
31.01.12
✎
17:01
|
||||
26
napagokc
31.01.12
✎
17:07
|
вопрос-то актуален? Если я не ошибаюсь, то тут идет банальная ошибка с обходом списка по циклу, при удалении строк этого списка. Если уж удаляешь элементы списка в цикле по этому списку, то обход нужно делать с конца списка на начало. Это стандартное правило для всех языков. Тут же идет неявная индексация с первого элемента до последнего. Вот и фигня получается. Думаю, в этом дело
|
|||
27
acsent
31.01.12
✎
17:11
|
юзай найтистроки
|
|||
28
dGU
01.02.12
✎
13:47
|
Всем спасибо. Думаю вопрос исчерпан.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |