Имя: Пароль:
1C
1С v8
Обход дерева значений
,
0 mzelensky
 
27.09.13
14:41
Доброго всем. Что-то никак не придумаю красивое решение.
Имеется дерево значений.

Ст1
  Ст1-1
     Ст1-1-1
     Ст1-1-2
  Ст1-2
     Ст1-2-1
С2
  Ст2-1
  Ст2-2
Ст3
  Ст3-1

Нужно обойти его так, чтобы обработать информацию на самых нижних уровнях, затем на один уровень выше, потом еще на уровень выше и так до конца. Т.е. для приведенного примера нужно:

Обработать строки на третьем уровне: Ст1-1-1, Ст1-1-2 и Ст1-2-1.
Далее обработать все строки второго уровня: Ст1-1, Ст1-2, Ст2-1, Ст2-2 и Ст3-1
И в последнюю очередь все строки первого уровня: Ст1, С2, Ст3

Вот как такую рекурсию написать?
1 Поросенок Петр
 
27.09.13
14:46
И в чем прикол обрабатывать Ст1-2-1 раньше чем Ст1-1 ?
2 Dmitry1c
 
27.09.13
14:47
(0) рекурсией
3 Поросенок Петр
 
27.09.13
14:49
(2) Да ну. А мужики то и не знали.

+(1) А если очень хочется, можно сначала обычным обходом собрать дерево в массив массивов (по уровням), а после уже обработать.
4 Euguln
 
27.09.13
14:52
(0) Рекурсией можно, но это будет цикл по уровням.
Согласен с (3) правильней преобразовать.
5 mzelensky
 
27.09.13
14:54
(4) вот и я прихожу только к циклу по уровням.
6 Serg_1960
 
27.09.13
15:05
(не вашим и не нашим) Можно запомнить порядок обхода элементов при рекурсии и после, в обратном цикле, - обработать
7 Лефмихалыч
 
27.09.13
15:07
Функция Обрабошить(СтрокаДерева)
   Для каждого Строка из СтрокаДерева.Строки Цикл
      Обрабошить(Строка);
      Строка.УгаУга = "ЫцЫц";//вот тут код обработки делай  после рекурсивного вызова
8 mzelensky
 
27.09.13
15:10
(7) чет мне кажется так не прокатит. По другому будет обходить.
9 kosts
 
27.09.13
15:15
(8) Нормально можно рекурсией сделать (если конечно не 100500 строк.
Я бы еще добавил условие окончание рекурсии, что то в этом роде:

Процедура Обрабошить(СтрокаДерева)
    Если СтрокаДерева.Строки.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    ...
10 kosts
 
27.09.13
15:17
Но порядок в рекурсии конечно будет не такой как ты хотел, но подчиненные узлы обработаются раньше своих родителей.
11 mzelensky
 
27.09.13
15:19
Наверное сделаю все-таки не сильно оптимально, но зато проще и работать будет 100%
12 Зойч
 
27.09.13
15:19
Посмотри как галочки трехцветные в деревьях ставят
13 mzelensky
 
27.09.13
15:20
(10) Сделать чтобы подчиненные узлы обрабатывались раньше родительских у меня не составляе трудностей.
14 mzelensky
 
27.09.13
15:20
(12) Это где такие галочки ставят?
15 kosts
 
27.09.13
15:24
Я бы тогда сделал массив.
Обошел бы рекурсией и записал в массив
Ссылку на строку и уровень в структуру. Потом в двойном вложенном цикле обошел по номерам уровней. Всё очень просто...
16 ProProg
 
27.09.13
15:25
Рекурсий 1 - нижние строки:

Процедура УстановитьАвторасчетЗаказа(Дерево,УстановитьРасчет=1)
    
    Подчиненные = Дерево.Строки;
    
    Для Каждого Подчиненный Из Подчиненные Цикл
        Если Подчиненный.ЭтоГруппа Тогда
        Иначе
            Если Подчиненный.Строки.Количество() = 0 Тогда
                    Подчиненный.Заказать = Подчиненный.РекомендуетсяЗаказать;
                    Подчиненный.СуммаВес = Подчиненный.Заказать * Подчиненный.ВесЕдиница;
            КонецЕсли;
        КОнецЕсли;
        УстановитьАвторасчетЗаказа(Подчиненный,УстановитьРасчет);
    КонецЦикла;
    
КонецПроцедуры
17 ProProg
 
27.09.13
15:26
Рекурсия 2 - итоги по звеньям дерева на основании более нижних:

Процедура СформироватьИтогиГруппДерева(Дерево)
    
    Подчиненные = Дерево.Строки;

    Для Каждого Подчиненный Из Подчиненные Цикл
        
        Если Подчиненный.Строки.Количество() = 0 Тогда
            Продолжить;
        КонецЕсли;

        СформироватьИтогиГруппДерева(Подчиненный);

        Подчиненный.Заказать = Подчиненный.Строки.Итог("Заказать");
        Подчиненный.РекомендуетсяЗаказать = Подчиненный.Строки.Итог("РекомендуетсяЗаказать");

     КонецЦикла;
            
КонецПроцедуры
18 ProProg
 
27.09.13
15:26
С тебя пузырь коньяка.
19 Euguln
 
27.09.13
15:38
(18) За что? По сабжу ничего. Простой рекурсией не решить. в (7) и (17) обработка узлов от конца к корню, а не по уровням.
20 ProProg
 
27.09.13
15:39
(19) глаза разбуй.
21 ProProg
 
27.09.13
15:41
проверка уровней всего еще несколько строк.
Но я думаю они нафиг не нужны, тк тут универсально.
22 Euguln
 
27.09.13
15:51
(20) Сам разуй, а лучше пройдись отладчиком, обработка дерева в (0) будет след:
Ст1-1-1
Ст1-1-2
Ст1-1
Ст1-2-1
Ст1-2
Ст1
Ст2-1
Ст2-2
С2
Ст3-1
Ст3
А надо:
Ст1-1-1
Ст1-1-2
Ст1-2-1
Ст1-1
Ст1-2
Ст2-1
Ст2-2
Ст3-1
Ст1
Ст2
Ст3
23 ProProg
 
27.09.13
15:56
(22) ептить. на какая разница. результат есть.
У автора элементарнейшая задача и не надо ее делать через зад.
24 Euguln
 
27.09.13
15:57
(23) Тогда тебе бутылку рыбьего жира, такой же коньяк, какая разница ))))
25 ProProg
 
27.09.13
16:00
(24) в дал две рабочих процедуры. рекурсии
Одна для просчета на нижних строка чо хоч.

Вторая как обратная - как раз для групп дерева делает итоги и расчеты. Причем по всем группам. любых уровней.
26 ProProg
 
27.09.13
16:00
например мы что то в дереве посчитали, теперь хотим чтобы итоги были в группах. так как они автоматом в дереве никогда не будут.
28 ProProg
 
27.09.13
16:01
а автора таже хрень: он что то там считает по строкам, потом хочет по группам получить итоги этих строк - больше чем 146 процентов.
31 Лефмихалыч
 
27.09.13
16:05
(0) можно добавить какую-то колонку в дерево, в которую записывать уровень в строках, а потом юзать НайтиСтроки(, Истина), кторая выгребет все подчиненные. ТОлько для этого надо точно знать количество уровней.
33 ProProg
 
27.09.13
16:06
у дерева есть метод Уровень.
35 Euguln
 
27.09.13
16:08
(31) Вариант, вместе с (33) обход одной рекурсией + сразу получаем кол-во уровней.
36 ProProg
 
27.09.13
16:12
Еще вариантик. Полезный

Процедура УстановитьРазворотСтрок(ДеревоПодбора, ДеревоПодбораНаФорме, УровеньРазворотаДерева) Экспорт
    
    Для Каждого СтрокаДерева0 Из ДеревоПодбора.Строки Цикл
        
        ЛокальныйУровеньРазворота = УровеньРазворотаДерева;
        
        Если СтрокаДерева0.Уровень() < ЛокальныйУровеньРазворота Тогда
            Если НЕ ДеревоПодбораНаФорме.Развернут(СтрокаДерева0) И СтрокаДерева0.Строки.Количество() > 0  Тогда
                ДеревоПодбораНаФорме.Развернуть(СтрокаДерева0, Истина);
            КонецЕсли;
        Иначе
            Если ДеревоПодбораНаФорме.Развернут(СтрокаДерева0) И СтрокаДерева0.Строки.Количество() > 0  Тогда
                ДеревоПодбораНаФорме.Свернуть(СтрокаДерева0);
            КонецЕсли;
        КонецЕсли;
        
        УстановитьРазворотСтрок(СтрокаДерева0, ДеревоПодбораНаФорме, УровеньРазворотаДерева)        
    КонецЦикла;

КонецПроцедуры
37 Лефмихалыч
 
модератор
27.09.13
16:13
(33) спасибо, кэп, дальше чо? По этому уроню нельзя отобрать с подчиненными
38 Euguln
 
27.09.13
16:15
(36) Запустил глобальный поиск ".Строки"?
39 ProProg
 
27.09.13
16:15
Да чо вы паритесь. в несколько рекурсивных обходов задача будет решена. Все что нужно передать параметр номера уровня который нудно обойти.
И сделать вызовы столько раз сколько нужно.
40 Лефмихалыч
 
27.09.13
16:16
(39) дак в несколько обходов-то и дурак сможет. Хочется же красоты и легкости
41 Euguln
 
27.09.13
16:18
Все, расходимся. (39) разрулил ситуацию.
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой