Каталог решений - Перебор всех строк дерева значений в глубину

Описание

Процедура перебора всех строк дерева значений. Перебор осуществляется вглубь дерева значений. То есть, если у строки есть починенные строки, то будет выбрана первая подчиненная строка. Если и у этой строки есть подчиненные строки, то опять же будет выбрана первая подчиненная строка. Если подчиненных строк нет — будет выбрана следующая строка на том же уровне, что и текущая строка. Если нет ни подчиненных строк, ни следующих строк на том же уровне, что и текущая строка, то ищется следующая строка после родителя текущей строки. При неудаче обрабатывается родитель родителя и далее вверх по структуре дерева значений.

Представленное на картинке дерево значений через процедуру обработает строки в следующем порядке — Строка1, Строка2, Строка3, Строка4, Строка5, Строка6, Строка7, Строка8.

 

Процедура ПереборВсехСтрокДереваЗначений()
    СтрокаДЗ=СледующаяСтрокаДЗ(НужноеДеревоЗначений);
    Пока СтрокаДЗ<>Неопределено Цикл
        //
        //обработка строки дерева значений
        //
        СтрокаДЗ=СледующаяСтрокаДЗ(НужноеДеревоЗначений, СтрокаДЗ);
    КонецЦикла;
КонецПроцедуры

// Выбор следущей строки дерева значений после переданной в качестве параметра строки.
//Следующей строкой считается первая из найденных - 1)первая подчиненная строка; 2)следующая строка на уровне
//с переданной строкой; 3)следующая строка на уровне родителя переданной строки; 4)если пункт 3 не привел
//к результату, то обрабатывается родитель родителя и далее вверх по иерархии дерева значений.
//Если переданная в качестве параметра строка является последней в дереве значений, то вернется Неопределено.
//
// Параметры:
//  текДЗ - ДеревоЗначений - днерево значений в котором осуществляется выбор следующей строки
//  текСтрокаДЗ - Неопределено - выбор первой строки корня дерева значений
//              - СтрокаДереваЗначений - строка дерева значений после котрой необходимо найти следующую строку
//
// Возвращаемое значение:
//  Неопределено - после переданной строки дерева значений отсутствуют строки или в дереве значений строки отсутствуют.
//  СтрокаДереваЗначений - следующая строка в дереве значений, расположенной после переданной строки дерева значений,
//                         либо первая строка корня дерева значений (если переданная строка дерева значений равна Неопределено)
//
Функция СледующаяСтрокаДЗ(текДЗ, текСтрокаДЗ=Неопределено)
    СтрокаВозв = Неопределено;
    Если текСтрокаДЗ=Неопределено Тогда //с самого начала дерева значений
        СтрокаВозв = ?(текДЗ.Строки.Количество()=0, Неопределено, текДЗ.Строки[0]);
    Иначе
        Если текСтрокаДЗ.Строки.Количество()<>0 Тогда  //есть подчиненные строки - заходим внутрь
            СтрокаВозв = текСтрокаДЗ.Строки[0];
        Иначе
            ОбрабатываемаяСтрокаДЗ = текСтрокаДЗ;
            Пока ОбрабатываемаяСтрокаДЗ<>Неопределено Цикл
                РодительОбрабСтрДЗ = ОбрабатываемаяСтрокаДЗ.Родитель;
                СтрокиНаУровнеОбрабСтрокиДЗ = ?(РодительОбрабСтрДЗ=Неопределено, текДЗ.Строки, РодительОбрабСтрДЗ.Строки);
                Если СтрокиНаУровнеОбрабСтрокиДЗ.Количество()>(СтрокиНаУровнеОбрабСтрокиДЗ.Индекс(ОбрабатываемаяСтрокаДЗ)+1) Тогда
                    СтрокаВозв = СтрокиНаУровнеОбрабСтрокиДЗ[СтрокиНаУровнеОбрабСтрокиДЗ.Индекс(ОбрабатываемаяСтрокаДЗ)+1];
                    Прервать;
                Иначе
                    ОбрабатываемаяСтрокаДЗ = РодительОбрабСтрДЗ;
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЕсли;
    Возврат СтрокаВозв;
КонецФункции

ps. Уточню, что данный перебор не оптимален в подавляющем большинстве случаев. В подавляющем большинстве случаев стоит использовать рекурсию (найти примеры ее в сети не составляет труда).
В каких случаях следует присмотреться к использованию данного кода:
1. При необходимости влезть в большой кусок кода. То есть то, что раньше выполнялось один раз теперь необходимо выолнять со строками дерева значений. При этом кусок кода выполняемый в цикле затруднительно вынести в отдельную процедуру/функцию из-за значительного количества переменных, которые надо будет передавать в эту выделенную процедуру/функцию.
Но даже в этом варианте можно вызовом рекурсии получить все узлы дерева значений (и поместить их, например, в список значений или массив) и затем организовать цикл. Так проще и код лаконичнее.
2. Когда дерево значений в процессе обработки меняет состав узлов. Вот тогда и становится нужна функция СледующаяСтрокаДЗ().

has been added to your cart:
Оформление заказа