Мина замедленного действия в методе 1С8 «НайтиСтроки», и ... разминирование.
Разработка - Механизмы платформы 1С
Файлы
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний
Оформите подписку на компанию для решения рабочих задач
Оформить подписку и скачать решение со скидкойВы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
Немногие знают, что метод НайтиСтроки в 1С работает не всегда ожидаемым образом.
Программист предполагает, что после вызова метода строки в нем будут расположены в таком же порядке, как в исходной таблице значений. Но 1С это не гарантирует.
Поэтому рекомендую добавить в глобальный модуль две функции НайтиСтроки и ПослеНайтиСтроки и вызывать вместо М = ТЗ.НайтиСтроки(Структура) метод М = НайтиСтроки(ТЗ, Структура). Или последовательность: М= ТЗ.НайтиСтроки(Структура); ПослеНайтиСтроки(М, ТЗ);
Параметр ТЗ во второй метод передается для совместимости с 1с80, где нет функции Владелец() у строки табличной части.
Сам метод просто упорядочивает строки, чтобы они шли в такой же последовательности, как и в исходной таблице. За всю свою деятельность только один раз столкнулся с проявлением этой фичи. Надеюсь, в будущих релизах 1С будет гарантировать правильный порядок строк, чтобы избежать неочевидных ошибок из-за не ожидаемого поведения метода. Но, по имеющимся у меня данным, исправление метода не планируется, поэтому рекомендую взять на вооружение мой способ.
Если вы предложите более быстрый способ упорядочивания массива найденных строк, буду благодарен.
Функция НайтиСтроки(ТЗ, Структура) Экспорт
М = ТЗ.НайтиСтроки(Структура);
ПослеНайтиСтроки(М, ТЗ);
КонецФункции
Процедура ПослеНайтиСтроки(М, ТЗ = Неопределено) Экспорт
Если М.Количество() = 0 Тогда
Возврат;
КонецЕсли;
//Для совместимости с 1с80
Если ТЗ = Неопределено Тогда
ТЗ = М[0].Владелец();
КонецЕсли;
ТЗ2 = Новый ТаблицаЗначений();
ТЗ2.Колонки.Добавить("Индекс");
ТЗ2.Колонки.Добавить("Строка");
Для Каждого Эл ИЗ М Цикл
НСтр = ТЗ2.Добавить();
НСтр.Индекс = ТЗ.Индекс(Эл);
НСтр.Строка = Эл;
КонецЦикла;
ТЗ2.Сортировать("Индекс");
М.Очистить();
Для Каждого Стр2 ИЗ ТЗ2 Цикл
М.Добавить(Стр2.Строка);
КонецЦикла;
КонецПроцедуры
В приложенной обработке формируется массив строк, потом случайным образом перетасовывается, что эмулирует фичу метода НайтиСтроки, после чего порядок восстанавливается вызовом ПослеНайтиСтроки.

Вступайте в нашу телеграмм-группу Инфостарт
См. также
Механизмы платформы 1С Разработчик Бесплатно (free)
Разберем 15 мифов о работе платформы «1С:Предприятие 8» – как распространенных, так и малоизвестных. Начнем с классики: «Код, написанный в одну строку, работает быстрее, чем многострочный». Так ли это на самом деле?
16.07.2025 45546 TitanLuchs 109
Работа с интерфейсом WEB-интеграция Механизмы платформы 1С Бесплатно (free)
Веб-интерфейсы повышают качество внешнего вида приложений 1С, предсказуемы с точки зрения верстки, позволяют организовать удобные и высокопроизводительные рабочие места для пользователей. Расскажем об особенностях разработки веб-интерфейсов на React внутри 1С, двустороннем взаимодействии 1С и JavaScript, а также сборке веб-приложения в одностраничный файл.
19.06.2025 18569 zeegin 15
Механизмы платформы 1С Работа с интерфейсом Разработчик Стажер 1С:Предприятие 8 Бесплатно (free)
Про ООП в 1С и о том, как сделать свой код более кратким и выразительным при помощи использования текучего интерфейса (fluent interface).
03.02.2025 25959 bayselonarrend 127
Механизмы платформы 1С Разработчик 1С:Предприятие 8 Бесплатно (free)
В этой статье подробно рассматривается работа с JSON в XDTO в 1С:Предприятие. Вы узнаете, как сериализовать и десериализовать объекты XDTO в JSON, интегрировать 1С с веб-сервисами и API, а также корректно обрабатывать данные при обмене. Разбираются особенности работы с коллекциями, использование функций восстановления и частые ошибки при работе с JSON и XDTO.
30.01.2025 33154 user2122906 10
Механизмы платформы 1С Файловый обмен (TXT, XML, DBF), FTP Разработчик 1С:Предприятие 8 Бесплатно (free)
Этот материал познакомит вас с механизмом XDTO (XML Data Transfer Objects) в 1С и научит эффективно использовать его возможности. Мы разберёмся, как работать с XML-схемами, создавать модели данных, манипулировать объектами XDTO, а также сериализовать и десериализовать их в XML. Вы узнаете, как использовать XDTO для интеграции с внешними системами, избегать типичных ошибок и оптимизировать код. К концу вы будете уверенно применять XDTO для решения сложных задач обмена данными и автоматизации процессов.
17.01.2025 55514 user2122906 13
Механизмы платформы 1С WEB-интеграция Разработчик 1С:Предприятие 8 Бесплатно (free)
В платформе 8.3.27 появилась возможность использовать WebSocket-клиент. Давайте посмотрим, как это все устроено и чем оно нам полезно.
14.01.2025 46661 dsdred 110
Механизмы платформы 1С Разработчик 1С:Предприятие 8 Бесплатно (free)
Особенности "Знач" и разбор документации к нему.
10.01.2025 26356 VAAngelov 60
Механизмы платформы 1С Разработчик Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)
Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.
23.06.2024 40355 bayselonarrend 24
Вот сколько пишу на восьмерке, ни разу не предполагал что строки будут расположены в таком же порядке, как в исходной таблице. Где это может понадобиться? Если на порядок закладываешься, то контролируй этот порядок сам.
(2) А где такое может понадобиться? Если сильно надо что-то найти в большой таблице - делаю через запрос (с использованием временных таблиц).
Вообще-то все задачи распределения, партионного списания (не только по товарам, есть задачи списания, где важна последовательность). Короче везде, где НайтиСтроки используется для отсортированной таблицы. У меня - сплошь и рядом.
Если в небольшой, то не проще ли вообще отказаться от стандартного метода НайтиСтроки()? Тупо перебираем строки в исходной таблице, проверяем условие поиска, если Истина, то добавляем найденную строку в результирующую таблицу (или в массив строк, смотря, что нужно получить). Против Ваших двух циклов в процедуре ПослеНайтиСтроки() будет один цикл по исходной таблице.
Вы можете возразить, что если в исходной таблице 10000 строк, а НайтиСтроки() возвращает 10, то два цикла по 10 строк заведомо быстрее одного цикла по 10000 строк. Но я отвечаю конкретно на пост (6), "если в небольшой". А если в "большой", то присоединяюсь к посту (3) "запрос (с использованием временных таблиц)".
Хотя допускаю, что бывают ситуации, когда исходная таблица не мала не велика, и предложенный Вами алгоритм будет оптимальным.
По поводу типовых спорить не буду, но я достаточно часто использую найтистроки в отсортированных таблицах, поэтому для тех, кто аналогично использует метод, привожу противоядие.
Тема о порядке строк проскакивала и на партнерском, да и по логике понятно, что народ будет юзать найти строки, т.к. обработка таблиц значений проще, чем работа с запросами.
(11) а я встречал, да и на партнерском тема тоже озвучена. Индексирование таблицы ускоряет поиск, но может привести к нарушению последовательности строк. Многие даже и не знают о такой фиче.
Признаюсь, списание по партиям упустил из виду. Но, как тут уже заметили, это вина программистов, которые не читают документацию.
Был забавный случай в УПП для Украины 1.0 (которая ещё под 8.0 была).
Там в отчете Обороты счета (или Анализ счета, запамятовал уже) данные по счетам в колонки выводились с использованием что-то типа:
СоответствиеСчетов = Новый Соответствие;
... заполнение ...
Для Каждого Счет Из СоответствиеСчетов Цикл
...
КонецЦиклаТак вот, в 8.0 Соответствие обходилось всегда в том же порядке, в котором в него добавлялись элементы. В 8.1 это поведение изменилось, и порядок обхода стал другим (в документации, кстати, и в 8.0 было написано, что порядок обхода не определен).
Естественно, отчет при переходе на 8.1 выводил белиберду.
Мне этот момент хорошо запомнился :)
--
Ещё неплохой момент с библиотекой glibc в Linux.
В документации сказано, что memcpy предназначена только для копирования непересекающихся областей памяти. Поведение в случае пересекающихся неопределено. Что, впрочем, непомешало криворуким программистам Adobe использовать именно эту функцию в Flash Player (вместо memmove, которая как раз отработает правильно всегда).
С очередным обновлением glibc звук в Flash Player стал хрипеть, а именно - потому, что в glibc оптимизировали функцию memcpy, и её поведение изменилось (всё также в пределах документации).
--
К чему это я. Криворукие программисты есть не только в 1С :)
В запросах тоже порядок не гарантируется, тут уж как индекс на диск положен. ТЗ скармливаю запросу как временную таблицу, мне нужно получить некоторые данные, а совать на вход в запрос все данные из ТЗ - ресурсоёмко, много их.
Редко, но нужно.
(5) echo77, собственно выше и смежный пример. Есть некая ТЗ, помимо прочих столбцов (с данными) незаполнены артикулы номенклатуры, нужно получить их из справочника. Позиций номенклатуры в ТЗ на порядки меньше количества её в справочнике. Естественно это будет запрос, вот только построчный поиск соответствий - путь низкой квалификации, или раздолбайства (когда время выполнения выходит за разумные пределы).
Данные в ТЗ забираю из базы данных oracle. Если кто не знает, то 1С до Оракла по возможностям языка очень далеко. В 1С нет ни case в order by, ни аналитических функций, ни прочих фишек. Поэтому грех не воспользоваться возможностями для сортировки, чтобы потом в 1С не пересортировывать дикими способами.
Так вот после того как отсортированная Ораклом ТЗ попала в 1С я делаю выборку из нее с помощью НайтиСтроки().
И мне нужно сохранить порядок, а его нет....
Для себя решил поставить перебор таблицы вместо НайтиСтроки().
Первое, что мне пришло на ум, это выбрать строки, а потом удалить их из таблицы. Хотя при последовательно переборе элементов массива и удалением строк из ТЗ методом Удалить(<СтрокаТаблицыЗначений>) все должно пройти корректно.
Для случая когда известны поля сортировки и не нужна связь с исходной таблицей.
НайдСтроки = ТЗ.НайтиСтроки(Структура);
тз2 = ТЗ.Скопировать(НайдСтроки);
ТЗ2.Сортировать(строкаСортировки);
тз2 = ТЗ.Скопировать(СтруктураОтбора);
ТЗ2.Сортировать(строкаСортировки)
Циатта из синтакс-Помощника:
Вариант синтаксиса: Скопировать по отбору
Скопировать(<ПараметрыОтбора>, <Колонки>)
Параметры:
<ПараметрыОтбора> (необязательный)
Тип: Структура.
Ключ структуры - идентификатор колонки, а значение структуры - значение отбора.
<Колонки> (необязательный)
Тип: Строка.
Список колонок для копирования в формате: "Колонка1, Колонка2...".
---------------
про порядок строк при копировании нигде не сказано поэтому новую таблицу надо отсортировать по образцу исходной.
---------------
забавный вариант удаления лишних строк из таблицы:
ТЗ=ТЗ.Скоприровать(новый Структура("ИмяКолонки",ЗначениеРеквизита))
Да, читал, но быстро запамятовал, просто тут из ничего такую пургу раскрутили, что никак тема из головы моей не выходила, зачем?.
Вы не указали, чем такой метод по-вашему плох.
Что это вообще означает? У вас же точно такая же сортировка...
М.Очистить();
и при чем тут отбор?
По 54 - кто отменил обращение к таблице по индексу? ТЗ[ТекущаяСтрокаТЗ2.индекс] - чем вам не ссылка на основную строку ТЗ?
Простите, но, по-моему, вы баламут.
Довольно распространенная в моей практике задача - есть большая отсортированная таблица значений, сортировали ее ранее, другими алгоритмами, фиг знает как. Суть не в этом. Я должен выполнить по ней списание по партиям товара из другой ТЗ (просто список товаров), уменьшая количество в этой большой таблице значений.
Перебираю строки маленькой таблицы, нахожу подходящие строки в большой таблице и последовательно списываю.
Если порядок НайтиСтроки нарушается, то возникают проблемы.
А вы о чем, что-то я не понял?
Например декларируем ФИФО, а реализуем рандом. У меня на поиск ошибки тогда ушло пол дня. На багфикс 1 минута.
(25) все же должны быть какие-то стандарты принятые в отрасли. Еще одной подставой было преобразование в строку по региональным стандартам чисел, а не просто в 232983928392.1234. Это только в 1С так. Есть стандарты в отрасли программирования и их надо соблюдать.
Неправильно ты, дядя фиксин, восьмерку ешь. Надо колбасой вниз. Так вкуснее будет.
Нафиг изобретать велосипеды.
Имхается, что по быстродействию будет тоже самое.
Автор, приведи еще примеры использования...
Все фичи 1с знать невозмножно, поэтому эта статья - огромный такой варнинг! ;-)
Помнится, когда я начинал работать с СУБД Oracle 20 лет назад, то в руководстве разработчика в самом начале изучения запросов было сказано, что результаты запроса - если не указана сортировка - не обязательно соответствуют физическому порядку строк в таблице. И все, больше никаких вопросов нет.
То есть из-за некачественной документации фирмы 1С и родилась и эта проблема, и дискуссия по ней.
Я согласен, что интуитивно человек ожидает вполне определенную сортировку в данном случае, поэтому, если программа ведет себя не так, поставщик должен был добавить одно предложение в справочную систему, и закрыть вопрос.
Противникам таких "интуитивных ожиданий": конечно, все люди разные, и интуиция у всех по-разному работает. Так в том-то и дело, что можно было бы легко позаботиться обо всех, предупредить их ошибки и проблемы. А можно было...сделать как сделано.
Работа с деревом будет быстрее если вам надо обработать всю таблицу а не только выбранные строки.
другой вариант получения дерева из таблицы: (с использованием СКД)
да и метод, имхо, оставляет желать лучшего.
А почему бы не проставить индексы сначала еще В ТЗ, а потом
ТЗ2 = ТЗ.Скопировать(ТЗ.НайтиСтроки(Структура));
ТЗ2.Сортировать("Индекс");
Это на нескольких отборах, я думаю, хорошо скажется на производительности, да и короче текст намного...
2. Вот вы по ТЗ№3 определили что вам в строке Х из ТЗ№2 надо списать Нную сумму, и вы хотите в соответствующей строке ТЗ№1 убрать также Нную сумму. Ну так в строке Х ТЗ№2 есть столбец Индекс, который при обращении к таблице ТЗ№1 по индексу ласт вам ту самую строку:
Х = ТЗ2[5]; //- нужная(в данном конкретном случае именно 6я) строка в маленькой таблице
НужнаяСтрокаБольшойТаблицы = ТЗ[X.Индекс]; //- нужная строка в большой таблицеВы же свою БОЛЬШУЮ ТЗ№1 не пересортировываете по 100 раз, пока проводите списание и индексы не собьются... так?
Вы издеваетесь!!!?????
Сначала во всей ТЗ первоначальной проставьте в столбец индекс индекс строки перебором "для инд = 1 по ..."
Потом отбираете строки и сортируете уже новую ТЗ по столбцу индекс!!! Потом когда из строки Х в Табл.значений надо попасть в оригинальную строку вы обращаетесь к строке в ТЗ[СтрокаТаблЗначений2.Индекс].
Сколько раз можно одно и то же писать? Занимаетесь тут маразмом. Не зря вас видать в прошлый раз забанили.
К тому же сортировать таблицу по ключам дольше, чем сортировать таблицу по индексу. И копировать всю таблицу дольше, чем копировать индексы. не вижу преимущества вашего подхода.
Вы хоть сто раз 2+2 = 5 напишите, от этого утверждение не станет верным. Попробуйте включить логическое мышление.
Процедура ПередНайтиСтроки(ТЗ)
ТЗ.КОлонки.Добавить("МойИндекс", НекотореОписаниеОписаниеТипаЧисло);
для инд = 1 по ТЗ.Количество() цикл
ТЗ[Инд].МойИндекс = инд;
конеццикла;
КонецПроцедуры
Функция НайтиСтрокиВТЗ(ТЗ, СтруктураОтбора)
М = ТЗ.НайтиСтроки(СтруктураОтбора);
М.Сортировать("МойИндекс");
Возврат М;
КонецФункции
Процедура Х()
...
ПередНайтиСтроки(ТЗ);
...
<некий цикл перебора в котором осуществляется последовательная выбора из ТЗ новоявленным методом НайтиСтрокиВТЗ>
СтруктураОтбора = ...;
Строки = НайтиСтрокиВТЗ(ТЗ, СтруктураОтбора);
для инд = 1 по Строки.Количество() цикл //цикл всего лишь чтобы показать
//как осуществлять обращение к основной ТЗ, вместо того чтобы городить лишнее
Сообщить("обращение к оригиналу строки № " + строка(инд) + " из " +
строка(Строки.Количество()) + " выбранных: " + Строка(ТЗ[Строки[инд].МойИндекс].РеквизитТЗ));
<конеццикла>
инд = 0;
для каждого Строка из Строки цикл //цикл всего лишь чтобы показать
//как осуществлять обращение к основной ТЗ, вместо того чтобы городить лишнее
инд = инд +1;
Сообщить("обращение к оригиналу строки № " + строка(инд) + " из " +
строка(Строки.Количество()) + " выбранных: " + Строка(ТЗ[Строка.МойИндекс].РеквизитТЗ));
<конеццикла>
<конеццикла>
КонецПроцедуры ПоказатьПроверки синтаксиса нет - писал в блокноте.
При чем тут ваши ключи от квартиры где деньги... - беру ваш пример и убираю оттуда половину текста, оставил лишь образование столбца индекс, но не в выборке, а в основной таблице, и сортировку сразу после выборки. ЭТО ПОЧТИ И ЕСТЬ ВАШ ТЕКСТ! Только без лишнего типа такого:
p.s. К тому же привычка называть переменные и процедуры в виде зарезервированных платформой методов, процедур - дурной тон. Иногда можно напороться на неработоспособность куска программы из-за этого. Пару раз допускал такую ошибку, больше не хочется, терять от получаса на такой ерунде.
Функция НайтиСтрокиВТЗ(ТЗ, СтруктураОтбора)
М = ТЗ.НайтиСтроки(СтруктураОтбора);
М.Сортировать("МойИндекс");
Возврат М;
КонецФункцииНаверно вы имели ввиду
Функция НайтиСтрокиВТЗ(ТЗ, СтруктураОтбора,ИмяКолонкиИндекс)
ОтобраннаяТЗ = ТЗ.Скопировать(СтруктураОтбора,ИмяКолонкиИндекс);
ОтобраннаяТЗ.Сортировать(ИмяКолонкиИндекс);
Возврат ОтобраннаяТЗ;
КонецФункцииеще можно попробовать неправильный ваиант циклической ссылки - в каждой строке хранить ссылку на саму себя, зато полсе ТЗ.Скопировать(СтруктураОтбора,ИмяКолонкиИндекс+","+ИмяКолонкиССылки) мы получим Таблицу из двух колонок -индекс и ссылка на начальную ТЗ
Если уж дошли почти до конца топика, то могли прочитать и 63, и 66. Результаты теста вашего метода.
1 проход (по 1/6 ТЗ за выборку, с повторением предыд. результатов):
fixin | народ | fixin модиф. | i132
0.82 vs 1.24 vs 0.64 vs 2.09
2 прохода
1.64 vs 1.61 vs 1.3 vs 2.2
3 прохода
2.47 vs 1.97 vs 1.95 vs 2.43
6 проходов
4.92 vs 3.09 vs 3.89 vs 3.14
10 проходов (количество отобранных строк в сумме уже превышает количество строк таблице, некоторые строки учавтсвуют в нескольких результатах отбора)
8.23 vs 4.65 vs 6.48 vs 4.08
Так что, да, при условии, что таблица будет обходиться более чем на половину своего размера этот метод имеет смысл, и его производительность оказывается лучше чем выгружать всю ТЗ.
Процедура ПередНайтиСтроки4(ТЗ)
ТЗ.КОлонки.Добавить("МойИндекс", Новый ОписаниеТипов(Новый КвалификаторыЧисла(15,0)));
ТЗ.КОлонки.Добавить("МояСтрока", Новый ОписаниеТипов("СтрокаТаблицыЗначений"));
инд = 0;
Для каждого Строка Из ТЗ Цикл
Строка.мойИндекс = инд;
Строка.МояСтрока = Строка;
инд = инд + 1;
КонецЦикла;
КонецПроцедуры
Функция НайтиСтрокиВТЗ4(ТЗ, СтруктураОтбора)
М = ТЗ.Скопировать(СтруктураОтбора,"МойИндекс,МояСтрока");
М.Сортировать("МойИндекс");
Возврат М.ВыгрузитьКолонку("МояСтрока");
КонецФункции
Процедура ОсновныеДействияФормыМетод4(Кнопка)
Если ТЗ.Количество() = 0 Тогда
Возврат;
КонецЕсли;
ПередНайтиСтроки4(ТЗ);
Для А = 1 По Проходов Цикл
Строки = НайтиСтрокиВТЗ4(ТЗ, Новый Структура("инд1,инд5", 1, 3));
Сообщить("Количество " + строка(Строки.Количество()));
для каждого Строка из Строки цикл
инд2 = Строка.Инд1;
конеццикла;
КонецЦикла;
КонецПроцедуры Показатьp.s. Жаль что тут спойлеров нет, хоть тот же код прятать.
Только не понял, что такое методы народ и fixin_мод.
то что fixin - это родной метод, понятно.
Кстати, по замерам - на что больше всего тратится времени?
Можно попробовать выгружать индексы в список и пользоваться методом СортироватьПоЗначению, как вариант.
А что, на получение строки по индексу тратится много времени, что вы для нее колонку создали?
Суть вашей мысли - добавить столбец в таблицу, пронумеровать его порядком строк и сортировать по нему найденные строки.
Не забудьте, что у массива (именно его возращает метод НайтиСтроки) нет метода сортировки по колонке, извольте его написать, и чтобы это работало быстрее чем мой метод.
Учитывая, что добавление колонки с индексом и ее заполнение требует некоторых предварительных действий (моя процедура же просто заменяет стандартную), а эффективность не доказана, пока практичная ценность вашего метода еще не доказана.
Повторяю - напишите рабочую функцию в моей обработке, тогда поставим вам ЗАЧЕТ. Но как вариант принимается, правда пока не понятно, хороший ли это вариант...
К тому же, не вижу смысла добавлять колонку индекса, если индекс каждой строки и так можно получить методом Индекс()
точно?
fixin | народ | fixin модиф. (сек, замеры из отладки. Замер начинается на момент запуска процедуры с циклом выборки, заканчивается в момент окончания процедуры, инициализация и заполнение таблицы на 100к строк, сюда не входит).
Отбор по 1/6 части строк (по 2м столбцам, где нечетное и НомерСтроки % 6 = 3, хоть второе условие и заведомо делает первое предположение верным, машина об этом не знает).
1 проход
0.82 vs 1.24 (при этом 0.85 сек(68%) ушло на заполнение индекса в таблицу) vs 0.64
2 прохода
1.64 vs 1.61 vs 1.3
3 прохода
2.47 vs 1.97 vs 1.95
6 проходов
4.92 vs 3.09 vs 3.89
10 проходов (количество отобранных строк в сумме уже превышает количество строк таблице, некоторые строки учавтсвуют в нескольких результатах отбора)
8.23 vs 4.65 vs 6.48
при отборе по половине строк за 1 раз (отбор четных / нечетных строк)
fixin | normal | fixin mod.
1 проход
2.49 vs 1.94 vs 1.93
2 прохода
4.95 vs 3.0 vs 3.83
Модифицированный - читайте 66
Построчно разбирал только свой метод - народ. Корректировал методы заполнения столбца индексами. Большая часть времени? Количество проходов разное. Хотите посмотреть? Скачайте обработку из поста.
Если вы будете сортировать не СортироватьПоЗначению, то кроме индексов у вас там ничего не будет, и чтобы потом заполнить массив, вам придется опять же каждую строку выдергивать из ТЗ по ее индексу из отсортированного списка значений. Я пошел в модифицированном немного другим путем - сделал СортироватьПоПредставлению, где представление - представляет собой индекс. Если бы это было вам интересно, уже бы посмотрели код.
Может можно обойтись без сортировки?
смотрите, допустим мы получили методом найтистроки строки 12, 10, 45, 38, 41.
Их правильный порядок известен как-бы, ведь есть исходная таблица.
неужели никак нельзя расположить строки в этом порядке?
только после прочтения комментов понял, о чем статья ))
В (59) Necytij об этом и писал - находите индексы своих <строки 12, 10, 45, 38, 41> в исходной таблице, и по ним ищете эти же строки в таблице-результате. Ну и сортировка по какому-либо признаку. И все при условии - в таблице-результате не делали переиндексацию после сортировки (не сбивали индекс).
а программисты бывают не только криворукие, но и пьяные, обкуренные, уставшие, кормящие детей, играющие попутно в квейк и шахматы ну и в конец просто зае%$#ннные чем или кем либо... :)
а талант не пропьешь!!!
Вот как можно улучшить кнопку сортировать:
При правильном расположении рук возвращается всё в том же порядке, а не в каком-то хаотичном.
Следует не лепить костыли куда попало, а научится писать правильные алгоритмы.
При каких руках у вас возвращается предсказуемый порядок строк? Т.е. без танцев и бубнов с индексами на обеих берегах выдачи-получения данных вы получаете в результате запроса расположение записей, аналогичное их расположению в БД?
Либо вы открыли недокументированную фишку, которую разработчики БД упустили из виду (сама получилась), либо ничего не поняли из проблемы несинхронности порядка записей при их Создании-Записи-Чтении.
Т.е. проигнорировали саму эту проблему абсолоютно )
А вот спасибо Автор. Пиши ещё =)
Только что собирался использовать сей метод, решил отгуглить для копипаста, буду иметь ввиду.
Интуитивно ожидал сохранения порядка строк.
Кстати по поводу интуиции. Я это ожидал поскольку много лет работал с кодом, который получает весомый пакет данных. И только апосля упорно с ним работает, сортирует, раскладывает на классификаторы etc. Дело привычки обжувать данные в памяти, нежели тратить ресурсы на запросы к БД. Да и специфика такова, что в момент запроса, БД может физически испариться, я не говорю про возможные блокировки, ожидание в очереди.
То есть алгоритмы поиска придуманные для Я.В.У. почти все гарантируют сохранение порядка строк. Всё-таки непривычно, что 1С по каждому чиху запрос пользует.
P.S. Использовать не буду, но в мемориз покладу.
P.P.S. Товарищи защищавшие писателей справки 1С, ваша въедливость при чтении документации заставляет думать о большом количестве свободного времени. Заведите себе девушку, жену, любовницу или ещё какую личную жизнь. Это когда радуешься НЕ работе ;-). Столько просьб привести примеры из жизни на 1С. Господа, систем под которые пишутся скрипты или бинарный код великое множество. Весьма разнообразные области человеческой деятельности автоматизируются. Если кто-то вынужден въедливо читать документацию на родном мне языке, обдумывая запятые - значит это с системой что-то не так.
Столкнулся с тем, что после попытки повторно обработать документы они обрабатывались в неправильной последовательности. Массив для обработки там как раз отбирается этой функцией по полю "Пометка" исходной таблицы с отобранными для обработки документами. Стал копать - наткнулся на эту тему.
Так что:
1) люди(в т.ч. программисты 1с, т.к. это их обработка) всё-таки ожидают от этого метода правильный порядок строк
2) тема полезна, автору плюс
Добавьте только в функцию НайтиСтроки() строку:
Возврат М;
Кроме этого, можно было бы в статье написать, что данный способ можно использовать не только для таблиц значений, но и для табличных частей объектов. Только в случае табличной части в функцию ПослеНайтиСтроки() обязательно надо передавать вторым параметром ссылку на табличную часть, так как у её строки нет метода Владелец().
Каким образом у вас меняются "номера строк", если "номера строк" присваиваются при создании объекта (в данном случае это ТЗ)?
Т.е. как бы вы не тасовали записи, номера строк всегда будут по-порядку и от 1 до n-1 :))
А если имели ввиду "порядок строк", то к номерам строк это отношение не имеет. Точнее, порядок и определяет номера, но не наоборот.
Следовательно, либо вы:
- не писали некий механизм "При перепродажах использую аналогичное"
- не разобрались, как этот механизм "При перепродажах" работает (и обратили внимание совсем не на суть механизма, а на следствие - номера строк)
- не поняли, в чем суть проблемы рассинхронизации порядка.
В общем-то, никто - ни Оракл, ни SQL, - не гарантируют расположение строк в выборке аналогично сорс-таблице. И честно об этом предупреждают. SQL даже идет дальше - предупреждает, что и обратное - соответствие порядка в записываемом наборе строк их физическому расположению при записи в базу, - нисколько не гарантирует.
И только 1с не считает нужным прозрачно все описывать (или не знает реальное положение дел), что дает повод писать статьи )).
и как же они смогут ГАРАНТИРОВАТЬ аналогичный порядок записей? каким механизмом?
Сергей, вы в статье описываете метод найти индекс в сорс-таблице, и присвоить этот же индекс в таргет-таблице (найдя поиском элемент), ежели такой элемент попал в таргет отбором.
А потом отсортировать таргет по индексу "а вот былО так".
Вам же предлагают проиндексировать сорс-таблицу, получить таргет (с индексами из сорс-таблицы) и отсортировать её по индексу.
Т.е. что быстрей - зависит от размеров таблицы. Но оброаботка полученных данных на1с-сервере перекроет любые временные "преимущества", полученные на данном первоначальном этапе выборки.
Процедура ПроверитьСортировкуМассива(МассивСоСтрокамиТЗ, ТЗ)
СписокДляСортировки = Новый СписокЗначений;
ТекущийИндекс = -1;
НадоСортировать = Ложь;
Для Каждого ЭлементМассива Из МассивСоСтрокамиТЗ Цикл
ИндексТЗ = ТЗ.Индекс(ЭлементМассива);
Если ТекущийИндекс > ИндексТЗ Тогда
НадоСортировать = Истина;
КонецЕсли;
ТекущийИндекс = ИндексТЗ;
СписокДляСортировки.Добавить(ЭлементМассива, ИндексТЗ)
КонецЦикла;
Если НадоСортировать Тогда
СписокДляСортировки.СортироватьПоПредставлению();
МассивСоСтрокамиТЗ = СписокДляСортировки.ВыгрузитьЗначения();
КонецЕсли;
КонецПроцедуры Показать
...
|УПОРЯДОЧИТЬ ПО
| ЭтоВозвратнаяТара ВОЗР,
| ДатаРеализации УБЫВ,
| ДатаПередачиТары ВОЗР";
...
...
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Для Каждого СтрокаТовары Из ТабличнаяЧастьВозврата Цикл
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("Номенклатура", СтрокаТовары.Номенклатура);
СтруктураОтбора.Вставить("Характеристика", СтрокаТовары.Характеристика);
СтруктураОтбора.Вставить("Серия", СтрокаТовары.Серия);
СтруктураОтбора.Вставить("Назначение", СтрокаТовары.Назначение);
НайденныеСтроки = РезультатЗапроса.НайтиСтроки(СтруктураОтбора);
Для каждого НайденнаяСтрока Из НайденныеСтроки Цикл
Если СтрокаТовары.Количество <= НайденнаяСтрока.Количество Тогда
...
Показать#Если _ Тогда
ДокСсылка = Документы.РасходнаяНакладная.ПустаяСсылка();
НоменклСсылка = Справочники.Номенклатура.ПустаяСсылка();
#КонецЕсли
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РасходнаяНакладнаяЗапасы.НомерСтроки КАК НомерСтроки,
| РасходнаяНакладнаяЗапасы.Номенклатура КАК Номенклатура
|ИЗ
| Документ.РасходнаяНакладная.Запасы КАК РасходнаяНакладнаяЗапасы
|ГДЕ
| РасходнаяНакладнаяЗапасы.Ссылка = &ДокСсылка
|
|УПОРЯДОЧИТЬ ПО
| НомерСтроки";
Запрос.УстановитьПараметр("ДокСсылка", ДокСсылка);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат;
КонецЕсли;
ТЗ = Результат.Выгрузить();
НайдСтроки = ТЗ.НайтиСтроки(Новый Структура("Номенклатура", НоменклСсылка));
ТЗ_Буф = ТЗ.Скопировать(НайдСтроки);
ТЗ_Буф.Сортировать("НомерСтроки Возр"); ПоказатьСогласен, но это не критично, так легло просто :)
(111)
Без проблем, ещё четыре строчки дописать:
МассивСтрок = Новый Массив;
Для Каждого ТекСтр Из ТЗ_Буф Цикл
МассивСтрок.Добавить(ТекСтр);
КонецЦикла;Так вот, при поиске, включающем поле НомерСтроки, отбор по номеру строки игнорируется.
После долгой переписки, 1Сы признали, что ошибка имеет место. Но когда исправят - неизвестно.
Насчет прикладного смысла - ну... есть все же такой прикладной смысл. Иначе бы это и не обнаружилось.
Причем, при поиске в упр.форме по отражению ТЧ, такой поиск нормально работает.
А в ТЗ оно выгружается только в целях возможности восстановления порядка строки при обратной загрузке.
Например, после выгрузки в ТЗ её можно пересортировывать для удобства обработки (пропорционального распределения, хронологической обработке по колонке дата и прочее), а перед обратной загрузкой в ТЧ - восстановить исходный порядок строк, отсортировав ТЗ по НомеруСтроки...
Вот и все её прикладное назначение.
Если уж нельзя искать по этому полю, так напишите про это в СП/ИТС, как про фичу... Делов-то.
Для чего нужен упорядоченный массив строк некой таблицы придумать не смог.
Но даже при таком раскладе алгоритм плох. Автор заводит новую ТаблицуЗначений (!), ищет строки в материнской ТаблицеЗначений (пусть по индексу, но всё-таки). Куча циклов, условий....
Автору нужно в школу, по моему.
КолВо = М.Количество() -1;
Для й = 0 по КолВо - 1 цикл
Для жи = й+1 по КолВо цикл
Если ТЗ.Индекс(М[й]) > ТЗ.Индекс(М[жи]) тогда //Туточки прописать условие сравнения строк, ведь не обязательно это индекс, в остатке по датам, наверное, дата прихода партии
ПеременнаяОбмена = М[й];
М[й] = М[жи];
М[жи] = ПеременнаяОбмена;
КонецЕсли;
КонецЦикла;
КонецЦикла; ПоказатьТем более автор не пишет про поиск, он пишет про сортировку. А я привёл пример сортировки в массиве без (!) дополнительных массивов, ТЗ, etc.
Мало того, мой пример универсальней: можно написать процедуру, в параметрах указать по какому столбцу сортировать.
Вы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 117041
Создание 14.02.12 20:23
Обновление 14.02.12 20:23
Просмотры 47593
Загрузки 16
Рейтинг
44
Комментарии 122
Код открыт Не указано
Рубрики Механизмы платформы 1С
Кому Разработчик
Тип файла Внешняя обработка (ert,epf)
Платформа 1С:Предприятие 8
Конфигурация 1C:Бухгалтерия
Операционная система Не имеет значения
Страна Россия
Отрасль Не имеет значения
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Абонемент ($m)