Как в 1С получить всех родителей для элемента ДереваЗначений?

Программист IT и автоматизация бизнеса
← На главную

В процессе работы с иерархическими структурами данных в 1С часто возникает необходимость, имея конкретную дочернюю строку объекта ДеревоЗначений, восстановить всю последовательность её родительских элементов вплоть до корневого уровня. Это критически важно для формирования полных путей, проведения иерархического анализа или реализации сложной бизнес-логики. В данной статье мы разберем наиболее эффективные способы решения этой задачи встроенными средствами платформы.

Мы детально изучим два проверенных подхода: итерационный метод с применением цикла Пока и классический рекурсивный метод. Каждый из них обладает своими преимуществами в зависимости от контекста задачи.

Решение 1: Итерационный подъем по иерархии через цикл `Пока`

Данный метод считается максимально надежным и производительным. Его суть заключается в пошаговом переходе от текущего элемента к вышестоящему, пока цепочка не прервется на самом верхнем уровне. Основным инструментом здесь выступает свойство Родитель, характерное для объекта СтрокаДереваЗначений. Если элемент является корневым, это свойство принимает значение Неопределено.

Алгоритм действий:

  1. Инициализируем новый массив для хранения найденных ссылок на родителей.
  2. Определяем стартовую точку — непосредственного родителя текущей строки.
  3. Запускаем цикл Пока, который продолжает работу до тех пор, пока переменная родителя содержит объект.
  4. Внутри цикла сохраняем текущего родителя в массив и переходим на уровень выше (присваиваем переменной родителя его собственного родителя).

Пример реализации алгоритма на языке 1С:


// Переменные:
// ИсходноеДерево - объект ДеревоЗначений
// ТекущаяСтрока - строка, чьих родителей мы ищем

МассивРодителей = Новый Массив;
Родитель = ТекущаяСтрока.Родитель;

Пока Родитель <> Неопределено Цикл
    МассивРодителей.Добавить(Родитель);
    Родитель = Родитель.Родитель;
КонецЦикла;

// В МассивеРодителей теперь содержатся все уровни иерархии: 
// от ближайшего предка до корня дерева.

Оптимизация: сохранение естественного порядка (сверху вниз)

Поскольку стандартное добавление в массив помещает элементы в конец, итоговый список будет инвертирован (снизу вверх). Если для логики вашего приложения требуется порядок от корня к дочернему элементу, рекомендуем использовать метод Вставить(0, Элемент). Это позволит сразу формировать правильную иерархическую последовательность.

Итоговая функция будет выглядеть так:


Функция ПолучитьМассивРодителей(СтрокаДерева) Экспорт

    МассивРодителей = Новый Массив;
    ТекущийРодитель = СтрoкаДерева.Родитель;

    Пока ТекущийРодитель <> Неопределено Цикл
        // Добавляем родителя в начало массива для сохранения порядка
        МассивРодителей.Вставить(0, ТекущийРодитель);
        ТекущийРодитель = ТекущийРодитель.Родитель;
    КонецЦикла;

    Возврат МассивРодителей;

КонецФункции

Результатом работы такой функции станет массив, где первым элементом будет самый верхний родитель, а последним — непосредственный предок переданной строки.

Решение 2: Рекурсивный метод обхода

Рекурсия представляет собой изящное решение для работы с любыми вложенными структурами. Метод базируется на самовызове функции для каждого вышестоящего уровня. Наполнение итогового массива происходит в момент «развертывания» стека вызовов.

Логика рекурсивного процесса:

  1. Процедура получает строку дерева и целевой массив.
  2. Проверяется наличие родительского элемента.
  3. При наличии родителя процедура вызывает саму себя для этого родителя (движение вверх).
  4. Только после завершения рекурсивного вызова элемент добавляется в массив (наполнение при возврате).

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

Реализация рекурсивного подхода:


// Основная функция для вызова
Функция ПолучитьРодителейРекурсивно(СтрокаДерева)
    
    МассивРезультат = Новый Массив;
    СобратьРодителей(СтрокаДерева, МассивРезультат);
    Возврат МассивРезультат;

КонецФункции

// Рекурсивная процедура
Процедура СобратьРодителей(СтрокаДерева, МассивРодителей)

    Родитель = СтрокаДерева.Родитель;
    Если Родитель <> Неопределено Тогда
        // Поднимаемся до самого корня
        СобратьРодителей(Родитель, МассивРодителей);
        
        // Добавляем элементы в массив на обратном пути
        МассивРодителей.Добавить(Родитель);
    КонецЕсли;

КонецПроцедуры

Рекурсивный код выглядит компактно, однако стоит помнить, что при экстремально большой глубине вложенности существует теоретический риск переполнения стека. В остальном он так же эффективен, как и цикл.

Выводы и рекомендации по выбору метода

Подводя итог, можно выделить следующие критерии выбора:

Понимание работы со свойством Родитель позволяет легко манипулировать иерархией любой сложности, обеспечивая корректное отображение и обработку данных в ваших программных решениях.

← На главную