Имя: Пароль:
1C
 
Оптимизация поиска в коллекциях значений
0 drugoimir
 
19.07.17
11:32
Добрый день.
Нужно оптимизировать алгоритм,  может кто-то натолкнет на верную мысль. Алгоритм взят из упп при расчете себестоимости.

Итак:
1) Есть  Структура (тип структура) состояний, она инициализируется динамически до цикла. В нее добавляются имена ключей поиска  для дальнейшего сравнения. Назовем ее СтруктураСостояний
2) Есть Соответствие (тип соответствие) параметров состояний параметров состояний. Ключом идет индекс состояния, а значением структура значений для этого состояния (ключи в этой структуре  всегда совпадают со структурой ключей из п.1). назовем ее Соответствие Параметров
3) Есть ТЗ, колонки в которой в том числе состоят из ключей стр п.1, но всего их больше, есть и другие колонки с именами "Сумма, количество" и т.п.

Далее идет примерно такой код:
Для Каждого Строка Из Таб Цикл // поиск выплняется полным перебором
        
        // Состояния-источники
        // Найдем состояние в соответсвии                
        НайденоСостояние=Ложь;
        Для Каждого ЭлементСостояние Из СоотвПараметровСостояний Цикл
            
            НайденоСостояние=Истина;
            Для Каждого Элемент Из СтруктураСостояния Цикл
                
                Если Элемент.Ключ = "ВременнаяРазница"или Элемент.Ключ = "ПостояннаяРазница" тогда
                    Продолжить;
                КонецЕсли;
                Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ]) Тогда
                    
                    НайденоСостояние = Ложь; // состояния различны
                    
                    Прервать; // дальше можно не проверять
                КонецЕсли;
            КонецЦикла;
            
            Если НайденоСостояние Тогда
                Прервать;
            КонецЕсли;
        КонецЦикла;


Получается что для каждого ключа из структура п.1 идет перебор и сравнения соотв. по этому ключу со строкой ТЗ.
1 aleks_default
 
19.07.17
12:58
НайденоСостояние  = Таб.НайтиСтроки(ЭлементСостояние.Значение).Количество()>0
2 mistеr
 
19.07.17
13:22
(0) Приведенный код это фактически соединение двух таблиц, хоть одна из них и в форме Соответствия.

Соответственно (каламбур невольный), первая мысль это перенести соединение в запрос.


Если это невозможно или нецелесообразно, пойдем дальше. Какого размера обычно бывают наборы входных данных (ТЗ и Соответствие)?
3 drugoimir
 
19.07.17
14:06
(0)(1) Так сделать нельзя, т.к. Поиск фактически идет в СоотвПараметровСостояний , которое заполняется в цикле. Лучше тогда приведу код  цикла полностью:
Для Каждого Строка Из Таб Цикл // поиск выплняется полным перебором
        
        // Состояния-источники
        // Найдем состояние в соответсвии                
        НайденоСостояние=Ложь;
        Для Каждого ЭлементСостояние Из СоотвПараметровСостояний Цикл
            
            НайденоСостояние=Истина;
            Для Каждого Элемент Из СтруктураСостояния Цикл
                
                Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
                    Продолжить;
                КонецЕсли;
                Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ]) Тогда
                    
                    НайденоСостояние = Ложь; // состояния различны
                    
                    Прервать; // дальше можно не проверять
                КонецЕсли;
            КонецЦикла;
            
            Если НайденоСостояние Тогда
                Прервать;
            КонецЕсли;
        КонецЦикла;
        
        Если НайденоСостояние Тогда
            ИндексСостояния = ЭлементСостояние.Ключ;
        Иначе
            // Переносим в соответствие
            СтрСост = Новый Структура;
            Для Каждого Элемент Из СтруктураСостояния Цикл
                Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
                    Продолжить;
                КонецЕсли;
                СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ]);
            КонецЦикла;
            
            ИндексСостояния = СоотвПараметровСостояний.Количество();
            СоотвПараметровСостояний.Вставить(ИндексСостояния, СтрСост);
        КонецЕсли;
        
        // Оставим в таблице ссылку на состояние
        Строка.Источник = ИндексСостояния;
        
        
        // То же самое для состояний-приемников
        // Найдем состояние в соответсвии                
        НайденоСостояние=Ложь;
        Для Каждого ЭлементСостояние Из СоотвПараметровСостояний Цикл
            
            НайденоСостояние=Истина;
            Для Каждого Элемент Из СтруктураСостояния Цикл
                
                Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
                    Продолжить;
                КонецЕсли;
                
                Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]) Тогда
                    
                    НайденоСостояние = Ложь; // состояния различны
                    
                    Прервать; // дальше можно не проверять
                КонецЕсли;
            КонецЦикла;
            
            Если НайденоСостояние Тогда
                Прервать;
            КонецЕсли;
        КонецЦикла;
        
        Если НайденоСостояние Тогда
            ИндексСостояния = ЭлементСостояние.Ключ;
        Иначе
            // Переносим в соответствие
            СтрСост = Новый Структура;
            Для Каждого Элемент Из СтруктураСостояния Цикл
                СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]);
            КонецЦикла;
            
            ИндексСостояния = СоотвПараметровСостояний.Количество();
            СоотвПараметровСостояний.Вставить(ИндексСостояния, СтрСост);
        КонецЕсли;
        
        // Оставим в таблице ссылку на состояние
        Строка.Приемник = ИндексСостояния;
        
    КонецЦикла;

Я так понял лучше всего соответствие СоотвПараметровСостояний  развернуть в Таблицу значений, сделать составной индекс и внутри нее производить поиск.
4 МихаилМ
 
19.07.17
14:09
(3)
зависит от типов данных для простых типов (дата,строка,число,булево)

соответствие работает быстрее.
5 drugoimir
 
19.07.17
14:15
(4) По текущему алгоритму получается, что мы перебираем соответствие. Для каждой его строки мы анализируем значение соответствия(структуру) по дин. ключу состояние (структура СтруктураСостояний тут тоже перебор) и сравниваем найденное значение структуры со строкой ТЗ Таб, где значение отбирается по этому же дин. ключу состояние

Т.е. прямого поиска в соответствии нет. Есть поиска по структуре, которая внутри него по дин. ключу.
6 H A D G E H O G s
 
19.07.17
14:23
(0) Дичь какая
7 H A D G E H O G s
 
19.07.17
14:25
Если в 2 и более таблицах данных ПОСТОЯННО много и хочется вывести производительность в идеал и получить батхерт от наследника - напиши свой mergejoin
8 H A D G E H O G s
 
19.07.17
14:30
Таблица1.Сортировать("КлючПоиска");
Таблица2.Сортировать("КлючПоиска");
Счетчик1=0;
Счетчик2=0;
Пока Истина Цикл
СтрокаТаблицы1=Таблица1[Счетчик1];
СтрокаТаблицы2=Таблица2[Счетчик2];
Если СтрокаТаблицы1.КлючПоиска>СтрокаТаблицы2.КлючПоиска Тогда
Счетчик2=Счетчик2+1;
ИначеЕсли СтрокаТаблицы1.КлючПоиска<СтрокаТаблицы2.КлючПоиска Тогда
Счетчик1=Счетчик1+1;
Иначе
СтрокаТаблицы1.ЗначениеИзТаблицы2=СтрокаТаблицы2.Значение;
КонецЕсли;
Если Счетчик1>=Таблица1.Количество() или четчик2>=Таблица2.Количество() Тогда
Прервать;
КонецЕсли;
КонецЦикла;


Как то так
9 H A D G E H O G s
 
19.07.17
14:31
(8) Ну и там граничные условия на заполненость таблиц