Синхронизация веток дерева значений

1. ixijixi 1978 06.12.24 10:13 Сейчас в теме
Коллеги, привет.

Есть дерево значений с заранее известной структурой (Категория/ВидПриемаПищи/Блюдо), но неизвестным количеством подчиненных веток.

Требуется сделать так, чтобы на каждом уровне вложенности (кроме верхнего) количество подчиненных веток было одинаковым.

Например, в категориях А и Б нужно, чтобы к-во приемов пищи было одинаковым. К примеру в категории А по факту был только завтрак+обед, в Б -завтрак+обед+ужин. Надо сделать так, чтобы в категории А было 3 подчиненных ветки.

То же касается и следующего уровня вложенности.

В результате параллельные ветки категорий должны стать одинаковыми по количеству веток.
Прикрепленные файлы:
Вознаграждение за ответ
Показать полностью
Найденные решения
23. Sashares 35 06.12.24 11:09 Сейчас в теме +2 $m
(22) Если мы сопоставляем по уровням дерева, вне зависимости от тип приема пищи то нет.

МаксимальноеКоличествоПриемовПищи = 0;
СоответствиеКоличестваИУровней = Новый Соответствие;
Для Каждого СтрКатегорий из Дерево.Строки Цикл
	КоличествоПриемовПищи = СтрКатегорий.Строки.Количество();
	МаксимальноеКоличествоПриемовПищи = Макс(КоличествоПриемовПищи ,МаксимальноеКоличествоПриемовПищи );
	Для Инд = 0 по КоличествоПриемовПищи -1 Цикл
		СтрПриемовПищи = СтрКатегорий.Строки[Инд];
		КоличествоБлюд = СтрПриемовПищи.Строки.Количество();
		КоличествоВСоответствии = СоответствиеПП [Инд];
		Если КоличествоВСоответствии = Неопределено Тогда
			КоличествоВСоответствии  = 0;
		КонецЕсли;
		СоответствиеПП [Инд] = Макс(КоличествоБлюд,КоличествоВСоответствии )
	КонецЦикла;
КонецЦикла;

Для Каждого СтрКатегорий из Дерево.Строки Цикл
	КоличествоПриемовПищи = СтрКатегорий.Строки.Количество();
	Пока КоличествоПриемовПищи< МаксимальноеКоличествоПриемовПищи Цикл
		СтрКатегорий.Строки.Добавить();
		КоличествоПриемовПищи = КоличествоПриемовПищи + 1;
	КонецЦикла;
	Для Инд = 0 по КоличествоПриемовПищи -1 Цикл
		СтрПриемовПищи = СтрКатегорий.Строки[Инд];
		КоличествоБлюд = СтрПриемовПищи.Строки.Количество();
		КоличествоВСоответствии = СоответствиеПП [Инд];
		Пока КоличествоБлюд< КоличествоВСоответствии Цикл
			СтрПриемовПищи.Строки.Добавить();
			КоличествоБлюд = КоличествоБлюд + 1;
		КонецЦикла;
	КонецЦикла;
КонецЦикла;
Показать
24. ixijixi 1978 06.12.24 11:44 Сейчас в теме
(23) Александр, спасибо.

Сделал в два прохода дерева, но немного по другому.

В первый проход получил соответствие количеств
Ключ Значение
Обед 5
Завтрак 4
"ПриемовПищиВКатегории" 2

Во второй проход добил ветки до нужного количества

	Количество = Новый Соответствие;
	
	Для Каждого Категория Из СтрокаОрганизации.Строки Цикл
		
		Ключ = "ПриемовПищиВКатегории";
		ТекущееКоличество = Количество.Получить(Ключ);
		Если ТекущееКоличество = Неопределено Тогда
			ТекущееКоличество = 0;
		КонецЕсли;
		
		Количество.Вставить(Ключ, Макс(ТекущееКоличество, Категория.Строки.Количество()));
		
		Для Каждого ПриемПищи Из Категория.Строки Цикл
			
			Ключ = ПриемПищи.ПриемПищи;
			ТекущееКоличество = Количество.Получить(Ключ);
			Если ТекущееКоличество = Неопределено Тогда
				ТекущееКоличество = 0;
			КонецЕсли;
			
			Количество.Вставить(Ключ, Макс(ТекущееКоличество, ПриемПищи.Строки.Количество()));
			
		КонецЦикла;
		
	КонецЦикла;
	
	Для Каждого Категория Из СтрокаОрганизации.Строки Цикл
		
		Ключ = "ПриемовПищиВКатегории";
		ТекущееКоличество = Количество.Получить(Ключ);
		ДополнитьСтроки(Категория, ТекущееКоличество);
		
		Для Каждого ПриемПищи Из Категория.Строки Цикл
			
			Ключ = ПриемПищи.ПриемПищи;
			ТекущееКоличество = Количество.Получить(Ключ);
			ДополнитьСтроки(ПриемПищи, ТекущееКоличество);
			
		КонецЦикла;
		
	КонецЦикла;
Показать
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. nomad_irk 80 06.12.24 10:19 Сейчас в теме
3. ixijixi 1978 06.12.24 10:21 Сейчас в теме
(2) Кода нет. Два дня впустую ((
5. nomad_irk 80 06.12.24 10:25 Сейчас в теме
(3) в общем случае будет что-то вроде такого:

ЭлементыДерева1 = Дерево1.ПолучитьЭлементы();
ЭлементыДерева2 = Дерево2.ПолучитьЭлементы();

РазницаВКоличестве = ЭлементыДерева1.Количество() - ЭлементыДерева2.Количество();

Если РазницаВКоличестве > 0 Тогда
     Для Сч = 1 По РазницаВКоличестве Цикл
          ЭлементыДерева2.Добавить();
     КонецЦикла;
ИначеЕсли РазницаВКоличестве < 0 Тогда
     Для Сч = 1 По -РазницаВКоличестве Цикл
          ЭлементыДерева1.Добавить();
     КонецЦикла;
КонецЕсли;
Показать
6. ixijixi 1978 06.12.24 10:31 Сейчас в теме
(5) Дерево изначально одно
8. nomad_irk 80 06.12.24 10:34 Сейчас в теме
(6) каким образом должно выполнятся разделение на 2 дерева? или разделения нет? категорий(веток дерева первого уровня) может быть сколько угодно?
13. ixijixi 1978 06.12.24 10:40 Сейчас в теме
(8) Два дерева и не нужно (как минимум необязательно), можно обойтись одним, главное чтобы количество подчиненных веток было одинаковым.

Категорий пока 2, но в дальнейшем не факт.
10. Sashares 35 06.12.24 10:37 Сейчас в теме
(6) Один раз обойти дерево и получить соответствие вида "Вид приема пищи" = "максимальное количество блюд".

Далее в цикл на 1 уровень дерева - в нем проверять что в данной категории есть все виды приема пищи из соответствия. Если нет - добавлять. Ну и количество строк по приему пищи добавлять, если меньше.
ixijixi; nomad_irk; user2116971; +3 Ответить
12. nomad_irk 80 06.12.24 10:40 Сейчас в теме
(10) Видов приемов пищи так же может быть разное количество, их так же нужно знать максимальное количество.
Т.е. придется как минимум 2 раза пробежаться по дереву, чтобы узнать максимумы по уровням вложенности.
14. user2116971 06.12.24 10:41 Сейчас в теме
(12)
Т.е. придется как минимум 2 раза пробежаться по дереву, чтобы узнать максимумы по уровням вложенности.
Можно в процессе добавления строк сохранять фактические максимумы в отдельное соответствие.
nomad_irk; +1 Ответить
15. nomad_irk 80 06.12.24 10:42 Сейчас в теме
(14) Да, это будет замечательно, если есть возможность вмешаться в процесс формирования дерева
18. Sashares 35 06.12.24 10:49 Сейчас в теме
(12)
Видов приемов пищи так же может быть разное количество, их так же нужно знать максимальное количество.


Если добавлять все виды приема пищи во все категории, тогда и не важно что где есть.
Если же нельзя добавлять, а надо как то сопоставлять, то вот я как-то даже не знаю.
В одном полдник и ужин в другом завтрак, обед и ужин - с чем сопоставлять полдник?
С завтраком или обедом?
19. nomad_irk 80 06.12.24 10:52 Сейчас в теме +0.2 $m
(18) так понимаю, сопоставление - не суть, суть - одинаковое количество записей по уровню
21. Sashares 35 06.12.24 10:55 Сейчас в теме
(19) Ну тогда не вид приема пищи, а уровень в дереве будет ключем.
2 значения надо нам:
1 - максимальное количество уровней в категории
2 - максимальное количество блюд в уровне - для этого соответствие
22. user2116971 06.12.24 11:00 Сейчас в теме
(21) Ну то есть два соответствия: Допустимые максимумы (для ограничения) и Фактические максимумы (для выравнивания)
23. Sashares 35 06.12.24 11:09 Сейчас в теме +2 $m
(22) Если мы сопоставляем по уровням дерева, вне зависимости от тип приема пищи то нет.

МаксимальноеКоличествоПриемовПищи = 0;
СоответствиеКоличестваИУровней = Новый Соответствие;
Для Каждого СтрКатегорий из Дерево.Строки Цикл
	КоличествоПриемовПищи = СтрКатегорий.Строки.Количество();
	МаксимальноеКоличествоПриемовПищи = Макс(КоличествоПриемовПищи ,МаксимальноеКоличествоПриемовПищи );
	Для Инд = 0 по КоличествоПриемовПищи -1 Цикл
		СтрПриемовПищи = СтрКатегорий.Строки[Инд];
		КоличествоБлюд = СтрПриемовПищи.Строки.Количество();
		КоличествоВСоответствии = СоответствиеПП [Инд];
		Если КоличествоВСоответствии = Неопределено Тогда
			КоличествоВСоответствии  = 0;
		КонецЕсли;
		СоответствиеПП [Инд] = Макс(КоличествоБлюд,КоличествоВСоответствии )
	КонецЦикла;
КонецЦикла;

Для Каждого СтрКатегорий из Дерево.Строки Цикл
	КоличествоПриемовПищи = СтрКатегорий.Строки.Количество();
	Пока КоличествоПриемовПищи< МаксимальноеКоличествоПриемовПищи Цикл
		СтрКатегорий.Строки.Добавить();
		КоличествоПриемовПищи = КоличествоПриемовПищи + 1;
	КонецЦикла;
	Для Инд = 0 по КоличествоПриемовПищи -1 Цикл
		СтрПриемовПищи = СтрКатегорий.Строки[Инд];
		КоличествоБлюд = СтрПриемовПищи.Строки.Количество();
		КоличествоВСоответствии = СоответствиеПП [Инд];
		Пока КоличествоБлюд< КоличествоВСоответствии Цикл
			СтрПриемовПищи.Строки.Добавить();
			КоличествоБлюд = КоличествоБлюд + 1;
		КонецЦикла;
	КонецЦикла;
КонецЦикла;
Показать
24. ixijixi 1978 06.12.24 11:44 Сейчас в теме
(23) Александр, спасибо.

Сделал в два прохода дерева, но немного по другому.

В первый проход получил соответствие количеств
Ключ Значение
Обед 5
Завтрак 4
"ПриемовПищиВКатегории" 2

Во второй проход добил ветки до нужного количества

	Количество = Новый Соответствие;
	
	Для Каждого Категория Из СтрокаОрганизации.Строки Цикл
		
		Ключ = "ПриемовПищиВКатегории";
		ТекущееКоличество = Количество.Получить(Ключ);
		Если ТекущееКоличество = Неопределено Тогда
			ТекущееКоличество = 0;
		КонецЕсли;
		
		Количество.Вставить(Ключ, Макс(ТекущееКоличество, Категория.Строки.Количество()));
		
		Для Каждого ПриемПищи Из Категория.Строки Цикл
			
			Ключ = ПриемПищи.ПриемПищи;
			ТекущееКоличество = Количество.Получить(Ключ);
			Если ТекущееКоличество = Неопределено Тогда
				ТекущееКоличество = 0;
			КонецЕсли;
			
			Количество.Вставить(Ключ, Макс(ТекущееКоличество, ПриемПищи.Строки.Количество()));
			
		КонецЦикла;
		
	КонецЦикла;
	
	Для Каждого Категория Из СтрокаОрганизации.Строки Цикл
		
		Ключ = "ПриемовПищиВКатегории";
		ТекущееКоличество = Количество.Получить(Ключ);
		ДополнитьСтроки(Категория, ТекущееКоличество);
		
		Для Каждого ПриемПищи Из Категория.Строки Цикл
			
			Ключ = ПриемПищи.ПриемПищи;
			ТекущееКоличество = Количество.Получить(Ключ);
			ДополнитьСтроки(ПриемПищи, ТекущееКоличество);
			
		КонецЦикла;
		
	КонецЦикла;
Показать
25. Sashares 35 06.12.24 11:56 Сейчас в теме
26. ixijixi 1978 06.12.24 12:00 Сейчас в теме
16. ixijixi 1978 06.12.24 10:44 Сейчас в теме
(10) Примерно так я и думал в начале))

Проблема в том, что при обходе 1-й категории нет прямого доступа ко 2-й.

Пробовал так

Строка1 = Дерево.Строки.Получить(0);
Строка2 = Дерево.Строки.Получить(1);

Количество = Макс(Строка1.Строки.Количество(), Строка2.Строки.Количество());

Пока Строка1.Строки.Количество() < Количество Цикл
	Строка1.Строки.Добавить();
КонецЦикла;
Пока Строка2.Строки.Количество() < Количество Цикл
	Строка2.Строки.Добавить();
КонецЦикла;
Показать


А дальше надо перейти на след. уровень, и тут затык
17. nomad_irk 80 06.12.24 10:48 Сейчас в теме
(16) Это решается рекурсией с передачей максимального количества в качестве одно из параметров вызова
либо в процессе формирования дерева, в узлах фиксировать максимальное количество и параметры не нужны.
20. Sashares 35 06.12.24 10:53 Сейчас в теме
(16)
СоответствиеПП = Новый Соответствие;
Для Каждого СтрКатегорий из Дерево.Строки Цикл
Для Каждого СтрПриемовПищи из СтрКатегорий.Строки Цикл
КоличествоБлюд = СтрПриемовПищи.Строки.Количество();
КоличествоВСоответствии = СоответствиеПП [СтрПриемовПищи.ВидПриемаПищи];
Если КоличествоВСоответствии = Неопределено Тогда
КоличествоВСоответствии  = 0;
КонецЕсли;
СоответствиеПП [СтрПриемовПищи.ВидПриемаПищи] = Макс(КоличествоБлюд,КоличествоВСоответствии )
КонецЦикла;
КонецЦикла;
Показать
4. user2116971 06.12.24 10:24 Сейчас в теме
И в чем проблема? Задать колонку "Ограничение", и программно её заполнять из фиасированного соответствия...
При добавлении (формальный синтаксис):
Если РодительскаяСтрока.Количество() > РодительскаяСтрока.Ограничение
Тогда ОтказОтДобавления.
Иначе ТекущаяСтрока.Ограничение = НастройкаУровней.Получить(ТекущаяСтрока.Уровень())

А перед печатью рекурсивно пробежать и добавить пустые строки, добив до максимума...
7. ixijixi 1978 06.12.24 10:32 Сейчас в теме
(4) Проблема в том, что обходя рекурсивно дерево, я натыкаюсь на то, что повторно обхожу ветки и начинаю сравнивать то, что уже сравнивал, уходя в бесконечный цикл
9. ixijixi 1978 06.12.24 10:35 Сейчас в теме
(4) Сначала подумал "легкотня", однако заходил с разных сторон (копировал дерево в две копии, рекурсивно добавлял строки в исходное дерево) натыкался на бесконечный цикл.
11. Sashares 35 06.12.24 10:38 Сейчас в теме
(9) Да не сложно так то. смотреть в 10
user2116971; +1 Ответить
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот