|
|
|
Пример рекурсии в 1с | ☑ | ||
|---|---|---|---|---|
|
0
Handlez
03.03.09
✎
16:54
|
Хочется посмотреть на пример рекурсии на встроенном языке 1с, только какой-нибудь реально используемый.
|
|||
|
1
vde69
03.03.09
✎
16:55
|
||||
|
2
ДенисЧ
03.03.09
✎
16:55
|
А что не получается?
|
|||
|
3
Classic
03.03.09
✎
16:55
|
Рекурсия - зло:)
|
|||
|
4
Mikeware
03.03.09
✎
16:56
|
Обработка СтруктураПодчиненности, например
|
|||
|
5
inka
03.03.09
✎
16:56
|
А чем рекурсия на языке 1С отличается от бычной рекурсии?
|
|||
|
6
ДенисЧ
03.03.09
✎
16:56
|
(3) Рекурсия - божестввенна (с)
|
|||
|
7
Handlez
03.03.09
✎
16:56
|
(2)Нет просто интересно, а в типовых ее нет.
|
|||
|
8
Fragster
гуру
03.03.09
✎
16:57
|
(7) а как же (4)?
|
|||
|
9
Guk
03.03.09
✎
16:58
|
(7) Есть. Например в ТиС это обработка ДеревоДокументов...
|
|||
|
10
DimG
03.03.09
✎
16:58
|
(7) В ПУБе тоже есть при расчете затрат
|
|||
|
11
Handlez
03.03.09
✎
16:58
|
(3) ПОчему зло?
(5) Нет, ну в том смысле как это реализуется именно с использованием языка самого. (8) Беру свои слова назад |
|||
|
12
Mikeware
03.03.09
✎
16:58
|
(3) ЕСли руки кривые, то и вызов оператор присваивания - зло...
|
|||
|
13
vde69
03.03.09
✎
16:59
|
(7) в отчетах бывает, например для обработки неопределенного уровня результата запроса
|
|||
|
14
Mikeware
03.03.09
✎
16:59
|
(11) А какая разница, на каком языке?
|
|||
|
15
Mikeware
03.03.09
✎
17:00
|
(13) Ага, практически в любом типовом отчете... ПечатьСтроки() вроде, рекурсивно вызывается...
|
|||
|
16
Handlez
03.03.09
✎
17:04
|
Спасибо, буду смотреть...
А в каких случаях ее вообще стоит применять? |
|||
|
17
Classic
03.03.09
✎
17:05
|
Ухты сколько любителей рекурсии.
Агрессивных и пряморуких |
|||
|
18
Fragster
гуру
03.03.09
✎
17:05
|
(16) для обхода дерева
|
|||
|
19
vde69
03.03.09
✎
17:05
|
(16) когда количестви итерраций ограничено разумными пределами, но заранее не извесно
|
|||
|
20
Fragster
гуру
03.03.09
✎
17:06
|
а вообще - для расчета факториала и числа фибоначчи, это в любом учебнике написано!
|
|||
|
21
Handlez
03.03.09
✎
17:06
|
(19) Ясно спасибо!
|
|||
|
22
DimG
03.03.09
✎
17:07
|
(16) именно как в (19) Иначе при порядка 10 тыс вызовов 1ска свалится почти наверняка. Проходил.
|
|||
|
23
vde69
03.03.09
✎
17:07
|
(18) а для зацикленого дерева?
это самые распространенные грабли, по этому пользоваться нужно с осторожностью |
|||
|
24
ДенисЧ
03.03.09
✎
17:08
|
(23) Зацикленное дерево - это не дерево :-)
|
|||
|
25
Fragster
гуру
03.03.09
✎
17:09
|
(23) а ты не цикли дерево :)
у меня считается "задача про рюкзак" применительно к складским ячейкам через рекурсию |
|||
|
26
Mikeware
03.03.09
✎
17:09
|
(24)"куст - это совокупность веток и листьев, торчащих из одного места"©армия
|
|||
|
27
Classic
03.03.09
✎
17:10
|
(22) Присоединяйся к клубу криворуких:)
|
|||
|
28
vde69
03.03.09
✎
17:12
|
(24) например анализ стека выполнения макроса VB, вроде раскладываеться в дерево, ан далеко не всегда... у меня специальный анализаитор для подстановки шаблонов сделан, для определения зацикливания рекурсии.
|
|||
|
29
Guk
03.03.09
✎
17:13
|
(24) +1
это граф... |
|||
|
30
DimG
03.03.09
✎
17:13
|
(27) Йа давно его президент
|
|||
|
31
ДенисЧ
03.03.09
✎
17:14
|
(28) как ты стек вызовов умудрился зациклить? Или тебе тоже в клуб? :-))
|
|||
|
32
0xFFFFFF
03.03.09
✎
17:17
|
Пипец в типовых нет. Ага.
В каждом отчете. |
|||
|
33
Ёпрст
гуру
03.03.09
✎
17:19
|
(32) тссс... народ просто ни разу не видел ВывестиГруппировку
:) |
|||
|
34
vde69
03.03.09
✎
17:19
|
(31) легко.... а в клубе я уже был - выгнали за криворукость :)
|
|||
|
35
Злопчинский
03.03.09
✎
18:35
|
решение задачи рюкзака - обсуждалосб здесь активно...
|
|||
|
36
zak555
03.03.09
✎
18:38
|
(0)
отчеты в Бюджетке 7-ке... например ОСВ по счету !!! |
|||
|
37
КонецЦикла
03.03.09
✎
18:49
|
В ТиС вывод группировок почти в каждом отчете
|
|||
|
38
Torquader
03.03.09
✎
21:09
|
Рекурсия смертельна для тех, кто любит глобальные переменные использовать.
|
|||
|
39
zak555
04.03.09
✎
12:12
|
(38)
пример можно... |
|||
|
40
los_hooliganos
04.03.09
✎
12:16
|
Функция ЕстьРодитель(Элемент,_Родитель)
Рез = 0; лРодитель = Элемент.Родитель; Пока (ПустоеЗначение(лРодитель) = 0)и(Рез=0) Цикл Рез = ?(лРодитель = _Родитель,1,0); лРодитель = лРодитель.Родитель; КонецЦикла; Возврат Рез; КонецФункции |
|||
|
41
zak555
04.03.09
✎
12:21
|
(40) и где тут по-твоему рекурсия?
|
|||
|
42
los_hooliganos
04.03.09
✎
12:32
|
(41) тфу
ну вот тебе из ТиС: //****************************************************************************** // ВывестиГруппировку(Запрос,Ном) // // Параметры: // Запрос - объект "Запрос" // Ном - номер выводимой группировки // // Возвращаемое значение: // Нет // // Вызывается из формул элементов диалога: // // Описание: // Выводит в печатную форму одну группировку запроса. Если // Есть нижележащие группировки, они выводятся также с использованием рекурсивного // вызова этой же процедуры. // Процедура ВывестиГруппировку(Запрос,Ном) ////ненужное убрано // если есть более детальная группировка - выведем ее Если КоличествоГруппировок > Ном Тогда ВывестиГруппировку(Запрос,Ном+1); КонецЕсли; КонецПроцедуры // ВывестиГруппировку() |
|||
|
43
FanatToNight
04.03.09
✎
12:36
|
(42) - только не горячись! спокойно!.. :)
|
|||
|
44
zak555
04.03.09
✎
12:38
|
(42) просил пример для поста (38), т.е. глобальные переменными
|
|||
|
45
Sserj
04.03.09
✎
12:46
|
(0) Видимо самое простое это получение полного наименование чего либо (со всеми вышестоящими группами).
Функция ПолноеИмя(Элемент, Имя = "") СоставноеИмя = СокрЛП(Элемент) + "\" + Имя; Если ПустоеЗначение(Элемент.Родитель) = 1 Тогда Возврат СоставноеИмя; Иначе Возврат ПолноеИмя(Элемент.Родитель, СоставноеИмя ); КонецЕсли; КонецФункции |
|||
|
46
ДенисЧ
04.03.09
✎
12:48
|
(45)
ПолноеНаименование() Синтаксис: ПолноеНаименование() Назначение: Возвращает строку, содержащую полное наименование выбранного элемента справочника со всеми вышестоящими уровнями, разделенными символом /. |
|||
|
47
Я не курил
04.03.09
✎
12:48
|
Для выборки с заранее неизвестным количество субконто используется часто
|
|||
|
48
Sserj
04.03.09
✎
12:58
|
(46) Это элементарный пример, возможно будет нужен, если к примеру в именах групп встречаются знаки /, можно заменить на свой разделитель.
Я подобное использовал при обмене - раскручивал иерархию справочников для сохранения всего дерева. |
|||
|
49
zak555
04.03.09
✎
13:03
|
так а где пример рекурсии с глобальными переменными!
|
|||
|
50
zak555
04.03.09
✎
13:03
|
???
|
|||
|
51
Злопчинский
04.03.09
✎
15:02
|
(49) по определению рекурсии - глобальные переменные там нафиг не нужны, они могут использоваться, но на сам факт выполнения рекурсии никоим образом не влияют...
|
|||
|
52
mrkorn
04.03.09
✎
15:20
|
(49) если голбальные переменные использовать в внутри рекурсии и менять их... или еще что-нибудь через них замутить...
но это пример криворукой рекурсии |
|||
|
53
DemMif
04.03.09
✎
15:27
|
Процедура Изменить()
перем сумма; Если ТЗ.ТекущаяКолонка()="БИК" Тогда сумма=ТЗ.БИК; Если ВвестиСтроку(Сумма,"Введите БИК", 9,0,0)=1 Тогда Если СтрДлина(Сумма)<9 ТОгда Предупреждение("Количество знаков должно быть 9"); Изменить(); СтатусВозврата(0); Возврат; КонецЕсли; ТЗ.УстановитьЗначение(ТЗ.ТекущаяСтрока(),ТЗ.ТекущаяКолонка(),Сумма); СделалиИзменения=1; КонецЕсли; ИначеЕсли ТЗ.ТекущаяКолонка()="КодУчастника" Тогда сумма=ТЗ.КодУчастника; Если ВвестиСтроку(Сумма,"Введите Код участника", 10,0,0)=1 ТОгда Если СтрДлина(Сумма)<10 ТОгда Предупреждение("Количество знаков должно быть 10"); Изменить(); СтатусВозврата(0); Возврат; КонецЕсли; ТЗ.УстановитьЗначение(ТЗ.ТекущаяСтрока(),ТЗ.ТекущаяКолонка(),Сумма); СделалиИзменения=1; КонецЕсли; ИначеЕсли ТЗ.ТекущаяКолонка()="НомерСчета" Тогда сумма=ТЗ.НомерСчета; Если ВвестиСтроку(Сумма,"Введите номер счета", 20,0,0)=1 ТОгда Если СтрДлина(Сумма)<20 ТОгда Предупреждение("Количество знаков должно быть 20"); Изменить(); СтатусВозврата(0); Возврат; КонецЕсли; ТЗ.УстановитьЗначение(ТЗ.ТекущаяСтрока(),ТЗ.ТекущаяКолонка(),Сумма); СделалиИзменения=1; КонецЕсли; ИначеЕсли ТЗ.ТекущаяКолонка()="ВидПлатежа" Тогда сумма=ТЗ.ВидПлатежа; Если ВвестиСтроку(Сумма,"Введите вид платежа (TELEPOST)", 2,0,0)=1 ТОгда Если СтрДлина(Сумма)<2 ТОгда Предупреждение("Количество знаков должно быть 2"); Изменить(); СтатусВозврата(0); Возврат; КонецЕсли; ТЗ.УстановитьЗначение(ТЗ.ТекущаяСтрока(),ТЗ.ТекущаяКолонка(),Сумма); СделалиИзменения=1; КонецЕсли; ИначеЕсли ТЗ.ТекущаяКолонка()="ДопИнфПоСотр" Тогда Если ВвестиСтроку(Сумма,"Введите дополнительную информацию о сотруднике", 100,0,0)=1 ТОгда ТЗ.УстановитьЗначение(ТЗ.ТекущаяСтрока(),ТЗ.ТекущаяКолонка(),Сумма); СделалиИзменения=1; КонецЕсли; ИначеЕсли (ТЗ.ТекущаяКолонка()="Сотрудник") или (ТЗ.ТекущаяКолонка()="НомерКода") Тогда ?(ТЗ.НомерСтроки>0,ОткрытьФорму(ТЗ.ПолучитьЗначение(ТЗ.НомерСтроки,"Сотрудник"),,1),""); КонецЕсли; КонецПроцедуры |
|||
|
54
1Сергей
04.03.09
✎
15:28
|
"Чтобы понять рекурсию, надо понять рекурсию" (С)
|
|||
|
55
DemMif
04.03.09
✎
15:28
|
Вот пример рекурсии. Не из типовой конфы.
|
|||
|
56
zak555
04.03.09
✎
16:41
|
(53)
1. это работать-то будет? 2. а зачем СтатусВозврата(0) в непредопределенной процедуре? |
|||
|
57
zak555
04.03.09
✎
16:45
|
(55)
вот пример рекурсии тоже из нетиповой: Функция Факториал(Чис) Возврат ?(Число(Чис)<=1, 1, Чис * Факториал(Чис - 1)); КонецФункции |
|||
|
58
Rie
04.03.09
✎
16:46
|
(56) Работать-то будет...
Но за такую рекурсию отстреливать надо. |
|||
|
59
Rie
04.03.09
✎
16:46
|
(57) И такую рекурсию - тоже не стоит использовать.
|
|||
|
60
DemMif
04.03.09
✎
16:46
|
(56)
1.Обработка досталось по наследству и все работает))). 2.не знаю... Можно убрать, только лень корректировать. |
|||
|
61
DemMif
04.03.09
✎
16:48
|
(0)
Автор никогда, слышишь, никогда не используй рекурсию! |
|||
|
62
Просто Лёха
04.03.09
✎
16:48
|
Функция ПолучитьРодителя(Сотр77,ВерхнийРодитель)
ПустойРодитель = Справочники.ФизическиеЛица.ПустаяСсылка(); Если Сотр77.Родитель.Выбран() = 0 тогда Возврат ВерхнийРодитель; КонецЕсли; КодРодителя = ДополнитьСтрокуСимволами(Сотр77.Родитель.Код,5,"0",0); НайдРод = Справочники.ФизическиеЛица.НайтиПоКоду(КодРодителя, Ложь); Если НайдРод <> ПустойРодитель тогда Возврат НайдРод; КонецЕсли; НовОбъект = Справочники["ФизическиеЛица"].СоздатьГруппу(); НовОбъект.Код = КодРодителя; НовОбъект.Наименование = Сотр77.Родитель.Наименование; НовОбъект.Родитель = ПолучитьРодителя(Сотр77.Родитель,ВерхнийРодитель); НовОбъект.Записать(); Возврат НовОбъект.Ссылка; КонецФункциb Вот пример при переносе данных через OLE с текущей иерархией |
|||
|
63
DemMif
04.03.09
✎
16:48
|
(62)-->(58)
|
|||
|
64
Просто Лёха
04.03.09
✎
16:50
|
(63) что там работать не будет? Перенесли справочник с сотрудниками более 3000 чел, все как по маслу
|
|||
|
65
Просто Лёха
04.03.09
✎
16:50
|
Из 77
|
|||
|
66
Просто Лёха
04.03.09
✎
16:50
|
(63) Со всей иерархией
|
|||
|
67
lalex23
04.03.09
✎
16:52
|
рекурсия - это красиво, как и слово так и код, но только если код красивый.
|
|||
|
68
Rie
04.03.09
✎
16:54
|
(60) 1. Много отвратительного кода - работает. От этого он не перестаёт быть отвратительным.
(61) Глупый совет. (63) В (62) использование рекурсии - весьма разумно. В (53) использование рекурсии несколько противоестественно. |
|||
|
69
DemMif
04.03.09
✎
16:55
|
(68)
Так, заинтриговали... Что можно изменить в процедуре (53). |
|||
|
70
zak555
04.03.09
✎
17:00
|
(59) почему?
|
|||
|
71
zak555
04.03.09
✎
17:01
|
самое красивое использование рекурсии в (36) - не нужно использовать 5 вложенных циклов!
|
|||
|
72
Rie
04.03.09
✎
17:05
|
(69) В (53) используется так называемая "хвостовая рекурсия" - то есть, рекурсивный вызов является последним исполняемым оператором рекурсивной процедуры.
Рекурсивная процедура с хвостовой рекурсией: Процедура Рек(Знач Х) Если Условие(Х) Тогда НекоторыеДействияЗависящиеОт(Х); Рек(НекотороеЗначениеЗависящееОт(Х)); КонецЕсли; КонецПроцедуры // Рек эквивалентна следующему: Процедура Нерек(Знач Х) Пока Условие(Х) Цикл НекотороеДействияЗависящиеОт(Х); Х = НекотороеЗначениеЗависящееОт(Х) КонецЦикла; КонецПроцедуры // Нерек При этом Нерек потребляет меньше памяти, работает быстрее, а выглядит ничуть не сложнее, чем Рек. Хорошие оптимизирующие компиляторы отлавливают случаи хвостовой рекурсии и сами преобразуют их в циклы. 1С не является (в данном вопросе) хорошим оптимизирующим компилятором. В (53) рекурсия является "хвостовой" - то есть, является _более туманным_ (с точки зрения чтения) и _медленнее работающим_ эквивалентом цикла. |
|||
|
73
Rie
04.03.09
✎
17:08
|
(70) Факториал - другой (по сравнению с (72)) вид рекурсии, преобразуемый в цикл.
_В 1С_ использование цикла _для таких случаев_ - проще и эффективнее (подчёркнутое - существенно). Недавно на этом форуме всплывал дурацкий пример с числами Фибоначчи, где _неправильное_ использование рекурсии повышало время вычислений с N до N*N. |
|||
|
74
DemMif
04.03.09
✎
17:16
|
(72)
А как в таком случае добиться, чтобы пользователь, к примеру ввел 9 знаков, а не меньше? |
|||
|
75
Rie
04.03.09
✎
17:22
|
(74)
Пока ВвестиСтроку(Сумма,"Введите БИК",9,0,0)=1 Цикл Если СтрДлина(Сумма)=9 Тогда // Сделать что надо с введенным значением Прервать; КонецЕсли; КонецЦикла; |
|||
|
76
zak555
04.03.09
✎
17:22
|
(73) ну так получается использование (57) допускается... правда не для больших чисел!
|
|||
|
77
DemMif
04.03.09
✎
17:28
|
(75)
Можно и так, только на скорость не влияет))) |
|||
|
78
zak555
04.03.09
✎
17:29
|
(77) влияет на использование оперативной памяти!
|
|||
|
79
Rie
04.03.09
✎
17:30
|
(77) Влияет. И на скорость, и на объём занимаемой памяти.
Помедитируй над тем, что происходит при рекурсивном вызове, а что происходит при переходе к следующему шагу цикла. |
|||
|
80
victuan1
04.03.09
✎
17:30
|
(0) Очень часто приходится мне на практике пользоваться рекурсией: перенос данных между конфами, разузлование спецификаций в производстве и пр.
Примеры те же, что и для паскаля. |
|||
|
81
DemMif
04.03.09
✎
17:31
|
(79)
Найду человека, который быстро набивает текст и посмотрю... |
|||
|
82
Rie
04.03.09
✎
17:31
|
(76) Я не спорю, что будет.
И я "за" рекурсию. Двумя руками. Но - применение рекурсии, как и любого другого средства, далеко не всегда целесообразно. |
|||
|
83
Rie
04.03.09
✎
17:32
|
(81) Любой человек набивает текст слишком медленно.
Сгенерируй _большой_ файл, замени ВвестиСтроку на чтение из файла - и замерь время. |
|||
|
84
DemMif
04.03.09
✎
17:33
|
(83)
Вот на чтения из файла я никогда не буду пользоваться рекурсией. |
|||
|
85
zak555
04.03.09
✎
17:34
|
(81) чего его искать...
можно итак понять - если использовать (53) и постояно делать "ошибкци", т.е. вызывать рекурсию, то стек вызова будет с каждым разом увеличиваться !!! а вот (75) - не будет! |
|||
|
86
Rie
04.03.09
✎
17:34
|
(84) А чем отличается ввод с клавиатуры от чтения из файла?
|
|||
|
87
zak555
04.03.09
✎
17:35
|
(82) я думаю, что её использование должно быть в умелых руках!
|
|||
|
88
DemMif
04.03.09
✎
17:36
|
(85)
Понятно объяснил... Спорить не буду... Но все же пользователю достаточно ошибится три раза. Не думаю, что пользователь ошибется 100 раз и более. |
|||
|
89
DemMif
04.03.09
✎
17:37
|
(86)
Смотря для чего... |
|||
|
90
zak555
04.03.09
✎
17:40
|
(88) - dblbvj yt dbltk ytjdys[ gjkmpjdfntktq!
|
|||
|
91
Rie
04.03.09
✎
17:40
|
(89) В данном случае - разницы нет.
|
|||
|
92
zak555
04.03.09
✎
17:40
|
(88) - видимо не видел нервных полльзователей
|
|||
|
93
DemMif
04.03.09
✎
17:57
|
Ладно, всем спасибо! Сегодня я стал умнее чуть-чуть...
|
| Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |