Имя: Пароль:
1C
 
Таблица значений в дерево значений.
,
0 kolts23381
 
02.01.15
17:13
Есть Таблица значений. Колонки у нее такие: категория,родительская категория,наименование категории. Нужно ее перевести в дерево значений. Какой алгоритм, а то бьюсь - не получается, пока только отсортировал таблицу :).
Желательно чтоб работало побыстрее, потому что кое как циклом и я сделаю но будет скорей всего медленно.
1 mehfk
 
02.01.15
17:34
Передай таблицу в запрос. Добавь ИТОГИ в запрос. Выгрузи в ДЗ. Профит.
2 kolts23381
 
02.01.15
17:38
А несколько уровней вложенности будет работать?
3 iceman2112
 
02.01.15
17:40
сколько записей в тз?
4 iceman2112
 
02.01.15
17:43
и откуда ты эту таблицу получил? Это не справочник?
5 kolts23381
 
02.01.15
17:46
Нет, это не справочник. Таблицу я получил из ТЕКДОКА(система подбора запчастей для автомобилей). Теперь нужно постоить дерево категорий запчастей.
6 kolts23381
 
02.01.15
17:49
В таблице где то 300 записей и где-то 4 уровня вложенности
7 iceman2112
 
02.01.15
17:56
тогда сделай так чтобы "категория" была индентификатором строки в ТЗ.
После первого цикла посчитаешь уровень вложенности для каждого элемента и максимально вложенный элемент, потом начнешь строить дерево с самого верхнего
8 iceman2112
 
02.01.15
17:58
получится что то районе 300х5 операции
9 iceman2112
 
02.01.15
18:11
Затупил, 300х2, после первого цикла сортируем во уровню вложенности или передаем таблицу в запрос и группируем по уровню вложенности, и после второго цикла уже получаем дерево
10 kolts23381
 
02.01.15
18:17
А можно подробнее, а то что то до меня не доходит.
11 kolts23381
 
02.01.15
18:18
Категория и родительская категория это числа а наименование это соответственно строка.
12 iceman2112
 
02.01.15
18:34
// выше должен быть код как мы переделываем таблицу чтобы индентификатор строки было значений поля "Категория"

ТаблицаЗначений.Колонка.Добавить("Уровень");
Для каждого СтрокаТаблицы Из ТаблицаЗначений Цикл

Уровень = 0;
СтрокаРодителя = ТаблицаЗначений.Получить(СтрокаТаблицы.РодительскаКатегория)
Пока СтрокаРодителя <> Неопределено Цикл
      СтрокаРодителя = ТаблицаЗначений.Получить(СтрокаРодителя.РодительскаКатегория);
      Уровень = Уровень + 1;
КонецЦикла;

СтрокаТаблицы.Уровень = Уровень;

КонецЦикла;

ТаблицаЗначений.Сортировать("Уровень");
ДеревоЗначений = Новый ДеревоЗначений;

// Дальше?
13 kolts23381
 
02.01.15
21:46
Кое какие подвижки есть, правда сделал по другому. Обычно когда что то долго не получается лучше оставить на завтра, но хочется добить. Сейчас другой косяк.
Есть на форме элемент таблица значений. Тип значения - деревозначений, то есть именно здесь я и хочу отображать свое дерево. но мне нужно чтоб отображалась только одно колонка, в переменной деревозначений у меня 3 колонки. Добавить колонку в сам элемент не срабатывает, создатьколонки() - создает 3 колонки. Попытался видимость колонок устанавивать в ложь но тогда вообще дерево не работает пропадают плюсики.
КАК быть?
14 Zhuravlik
 
02.01.15
21:48
(12) - это в качестве зарядки для мозгов. В (1) - дело говорит.
15 Souvenire
 
02.01.15
21:50
Ничо не понял. А какая религия не позволяет ТЗ в запрос пихнуть?
16 kolts23381
 
02.01.15
21:52
2 года писал запросы изучая нюансы по мере необходимости, но сейчас не знаю как это сделать :).
17 Zhuravlik
 
02.01.15
21:55
(13) "Есть на форме элемент таблица значений. Тип значения - деревозначений," - так и не понял, о чем это...

(16) Как-то так:

    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    МояТаблицаЗначений.Реквизит1,
        |    МояТаблицаЗначений.Реквизит2,
        |    МояТаблицаЗначений.Реквизит3
        |ПОМЕСТИТЬ МояТаблица
        |ИЗ
        |    &МояТаблицаЗначений КАК МояТаблицаЗначений
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    МояТаблица.Реквизит1 КАК Реквизит1,
        |    МояТаблица.Реквизит2 КАК Реквизит2,
        |    МояТаблица.Реквизит3 КАК Реквизит3
        |ИЗ
        |    МояТаблица КАК МояТаблица
        |ИТОГИ ПО
        |    Реквизит1,
        |    Реквизит2,
        |    Реквизит3";

    Запрос.УстановитьПараметр("МояТаблицаЗначений", МояТаблицаЗначений);
    РезультатЗапроса = Запрос.Выполнить();
    МоеДеревоЗначений = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
18 Souvenire
 
02.01.15
21:57
ТЗ из ТЧ документа? тогда типизация не нужна, можно как здесь:
v8: Добавить таблицу значений в запрос

Про типизацию здесь:
Книга знаний: Временные таблицы в 8.1 - обязательная типизация полей таблиц значений-источников

пример запроса в (17)
19 GANR
 
02.01.15
22:00
(1)(14)(15) В кои веки 1С-запросы (ИЕРАРХИЯ) помогали преобразовать таблицу вида (Отец, Сын, Поле1, поле2...) в дерево значений? СКД с Хрусталевским примером на 323 странице - это может быть, но я бы для решения этой задачи другой подход использовал.
(0) Для этого нужна РЕКУРСИЯ, на вход которой подаются "корневые" строки ТЗ - строки в которых Отец = Пусто, ну а далее - ищем для каждой строчки дочерние строки (где сын = отец, внук, правнук и пр.). Смысл понятен? Нагуглить сможешь?
20 Souvenire
 
02.01.15
22:03
(19) во все веки. Про клюшки не знаю.
21 GANR
 
02.01.15
22:07
(20) Если иерархия загнана в справочник или если дерево имеет фиксированный уровень вложенности - это поможет, но в топике ситуация явно другая.
22 kolts23381
 
02.01.15
22:08
Первым делом я гуглил. Так как когда у меня были деревья по программе в универе деревья я был далек от программирования и все списал то тему не усвоил. За 2 года эта надобность возникла в первый раз. Можно конечно отбросить мою обработку и погрузиться в дебри деревьев, но не сильно хочется.
Пока сделал вот так, предварительно отсортировав таблицу по значению родительскаякатегория.
СтруктураПоиска = Новый Структура;
МассивНайденныхСтрок = Новый Массив;    
Для К = 0 По ДеревоКатегорийТаблица.Количество()  - 1 Цикл
   СтруктураПоиска.Вставить("Категория",ДеревоКатегорийТаблица[К].РодительскаяКатегория);
   МассивНайденныхСтрок = ДеревоКатегорий.Строки.НайтиСтроки(СтруктураПоиска,Истина);
      Если массивНайденныхСтрок.Количество() > 0 Тогда
    ДеревоКатегорийСтрокаРодитель = МассивНайденныхСтрок[0];        
     Иначе
    ДеревоКатегорийСтрокаРодитель = ДеревоКатегорий;
     КонецЕсли;
    ДеревоКатегорийСтрока = ДеревоКатегорийСтрокаРодитель.Строки.Добавить();
    ДеревоКатегорийСтрока.Категория = ДеревоКатегорийТаблица[К].Категория;
    ДеревоКатегорийСтрока.РодительскаяКатегория =    ДеревоКатегорийТаблица[К].РодительскаяКатегория;
        ДеревоКатегорийСтрока.НаименованиеКатегории = ДеревоКатегорийТаблица[К].НаименованиеКатегории;
    КонецЦикла;
Вроде работает, буду проверять на предмет непредвиденных багов.
23 GANR
 
02.01.15
22:09
(22) Подай на вход алгоритму 3-7 уровней вложенности
24 kolts23381
 
02.01.15
22:10
4-5 отработает быстро около 10 думаю будет долго.
25 GANR
 
02.01.15
22:14
(24) в правильности уверен?
26 Souvenire
 
02.01.15
22:19
(21) "фиксированный уровень вложенности" - это откуда? динамически изменяющееся количество колонок? сейчас пять, а потом 28?
27 0xFFFFFF
 
02.01.15
22:21
Что за клюшечные мазохисты в ветке собрались? После 1го поста можно было закрывать.
28 kolts23381
 
02.01.15
22:23
(26) Нет это значит что у одной строки может быть 3 подстроки а у другой 6 а еще одной ни одной. Вложенность относится к строкам. Запросом из (17) не получилось. (22) Появляются иногда какие то 3 строки не в том месте.
29 Souvenire
 
02.01.15
22:30
(28) каждое поле, ИТОГИ по которой у тебя в запросе - в порядке следования и будут ветвями дерева. Я не понимаю о чем вы говорите.
30 kolts23381
 
02.01.15
22:42
ДеревоКатегорийТаблица - исходная таблица
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    МояТаблицаЗначений.Категория,
        |    МояТаблицаЗначений.РодительскаяКатегория,
        |    МояТаблицаЗначений.НаименованиеКатегории
        |ПОМЕСТИТЬ МояТаблица
        |ИЗ
        |    &МояТаблицаЗначений КАК МояТаблицаЗначений
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////

        |ВЫБРАТЬ
        |    МояТаблица.Категория КАК Категория,
        |    МояТаблица.РодительскаяКатегория КАК РодительскаяКатегория,
        |    МояТаблица.НаименованиеКатегории КАК НаименованиеКатегории
        |ИЗ
        |    МояТаблица КАК МояТаблица
        |ИТОГИ ПО        
        |Категория,
        |РодительскаяКатегория";

    Запрос.УстановитьПараметр("МояТаблицаЗначений", ДеревоКатегорийТаблица);
    РезультатЗапроса = Запрос.Выполнить();
    ДеревоКатегорий = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
Получается 3 уровня вложенности для каждой строки
31 kolts23381
 
02.01.15
22:46
По моему функция  ДеревоКатегорий.Строки.НайтиСтроки(СтруктураПоиска,Истина) Ищет только в непосредственных потомках
32 iceman2112
 
02.01.15
22:51
(27) Такие вот мазохисты, кинь запрос этот плз.
33 iceman2112
 
02.01.15
22:51
(31) Че гадать то, СП?
34 iceman2112
 
02.01.15
22:54
Я же тебе предложил отличный вариант, чтобы не заниматься такой ерундой типо, НайтиСтроки(), сделать идентификатором индекс категории она же - у тебя поле "категория"
35 Zhuravlik
 
02.01.15
23:07
(28) Из описания в (0) я сделал вывод о трех уровнях вложенности. И если таблицу значений нужно превратить в дерево - святая моя уверенность - в восьмерке только запросом. И быстрее, и проще для понимания.
Подобной проблемой я и сам страдал, когда сидел на клюшках - http://infostart.ru/public/121675/ - вот до чего дошел в итоге. Это по-сути и есть преобразование плоской таблицы в дерево значений, с произвольным количеством группировок. И то, в итоге пришел к индексированной таблице которая раз и навсегда отучила страдать всякой фигней :)
36 GANR
 
02.01.15
23:21
(27) Тогда вопрос: как указать запросу в секции ИТОГИ по какому полю строить иерархию неограниченного уровня вложенности? С иерархическим справочником то просто - там платформа сама все определит.
37 GANR
 
02.01.15
23:23
+(27) Да и какой это мазохизм - простенькая задачка требующая понимания рекурсивного механизма. Только и всего.
38 Zhuravlik
 
02.01.15
23:30
(36) "неограниченного уровня вложенности" - в исходном условии не было таких слов. Для этого либо динамически формировать текст запроса, либо конечно рекурсией.
(37) С рекурсией дольше. И код сложнее.
39 kolts23381
 
03.01.15
02:28
(33) Все не сплю, ковыряю. В общем проблема в том что дочерний узел создается раньше родительского это происходит из за того что индекс у него меньше чем у родительского. Надо либо нормализовать таблицу либо что-то другое думать. В принципе я так и думал что так может быть. Так и не дошли руки до твоего способа из поста (12), не разобрался я в нем пока.
40 GANR
 
03.01.15
12:46
(38) Вот динамически текст запроса строить ни за что бы не стал в подобных ситуациях. Рекурсии сколько помню реализовывал - всегда выходили 20-30 строчек. (39) Посмотри пункт 22 в топике v8: Заполнить ДеревоЗначений из иерархического справочника - может на идеи натолкнет. ЗЫ могу сам написать, но хочу чтобы автор поднялся в программировании на ступеньку выше.
41 kolts23381
 
03.01.15
14:15
Из (22) поста код работает но вылазят ошибки тогда когда ид категории меньше чем ид его родителя. То есть категория создается раньше чем ее родитель. В моем конкретном случае такого почти нет. Так как время поджимает я или оставлю так либо сделаю второй проход который будет это устранять.
Компьютер — устройство, разработанное для ускорения и автоматизации человеческих ошибок.