Имя: Пароль:
1C
 
Пример рекурсии в 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
Ладно, всем спасибо! Сегодня я стал умнее чуть-чуть...
2 + 2 = 3.9999999999999999999999999999999...