gifts2017

Мина замедленного действия в методе 1С8 «НайтиСтроки», и ... разминирование.

Опубликовал Осипов Сергей (fixin) в раздел Программирование - Практика программирования

В этой статье рассматривается небезопасная фича метода НайтиСтроки в 1с8 и описывается способ, позволяющий сделать вызов этого метода надежным.

Немногие знают, что метод НайтиСтроки в 1С работает не всегда ожидаемым образом.

Программист предполагает, что после вызова метода строки в нем будут расположены в таком же порядке, как в исходной таблице значений. Но 1С это не гарантирует.

Поэтому рекомендую добавить в глобальный модуль две функции НайтиСтроки и ПослеНайтиСтроки и вызывать вместо  М = ТЗ.НайтиСтроки(Структура) метод М = НайтиСтроки(ТЗ, Структура). Или последовательность: М= ТЗ.НайтиСтроки(Структура);  ПослеНайтиСтроки, ТЗ);

Параметр ТЗ во второй метод передается для совместимости с 1с80, где нет функции Владелец() у строки табличной части.

 

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

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

 

 

Функция НайтиСтроки(ТЗ, Структура) Экспорт

      
М = ТЗ.НайтиСтроки(Структура);

      
ПослеНайтиСтроки(М, ТЗ);

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



Процедура
ПослеНайтиСтроки(М, ТЗ = Неопределено) Экспорт

       Если
М.Количество() = 0 Тогда

             Возврат;

       КонецЕсли;

      
//Для совместимости с 1с80

      
Если ТЗ = Неопределено Тогда

            
ТЗ = М[0].Владелец();

       КонецЕсли;



      
ТЗ2 = Новый ТаблицаЗначений();

      
ТЗ2.Колонки.Добавить("Индекс");

      
ТЗ2.Колонки.Добавить("Строка");



       Для Каждого
Эл ИЗ М Цикл

            
НСтр = ТЗ2.Добавить();

            
НСтр.Индекс = ТЗ.Индекс(Эл);

            
НСтр.Строка = Эл;

       КонецЦикла;



      
ТЗ2.Сортировать("Индекс");

      
М.Очистить();

       Для Каждого
Стр2 ИЗ ТЗ2 Цикл

            
М.Добавить(Стр2.Строка);

       КонецЦикла;

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

 

В приложенной обработке формируется массив строк, потом случайным образом перетасовывается, что эмулирует фичу метода НайтиСтроки, после чего порядок восстанавливается вызовом ПослеНайтиСтроки.

 

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
down.zip
.zip 5,01Kb
14.02.12
16
.zip 5,01Kb 16 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

. Алекс Ю (AlexO) 02.03.12 16:14
(0)
Программист предполагает, что после вызова метода строки в нем будут расположены в таком же порядке, как в исходной таблице значений. Но 1С это не гарантирует.

В общем-то, никто - ни Оракл, ни SQL, - не гарантируют расположение строк в выборке аналогично сорс-таблице. И честно об этом предупреждают. SQL даже идет дальше - предупреждает, что и обратное - соответствие порядка в записываемом наборе строк их физическому расположению при записи в базу, - нисколько не гарантирует.
И только 1с не считает нужным прозрачно все описывать (или не знает реальное положение дел), что дает повод писать статьи )).
Надеюсь, в будущих релизах 1С будет гарантировать правильный порядок строк,

и как же они смогут ГАРАНТИРОВАТЬ аналогичный порядок записей? каким механизмом?
Сергей, вы в статье описываете метод найти индекс в сорс-таблице, и присвоить этот же индекс в таргет-таблице (найдя поиском элемент), ежели такой элемент попал в таргет отбором.
А потом отсортировать таргет по индексу "а вот былО так".
Вам же предлагают проиндексировать сорс-таблицу, получить таргет (с индексами из сорс-таблицы) и отсортировать её по индексу.
Т.е. что быстрей - зависит от размеров таблицы. Но оброаботка полученных данных на1с-сервере перекроет любые временные "преимущества", полученные на данном первоначальном этапе выборки.
0. Осипов Сергей (fixin) 14.02.12 23:21
В этой статье рассматривается небезопасная фича метода НайтиСтроки в 1с8 и описывается способ, позволяющий сделать вызов этого метода надежным.

Перейти к публикации

1. Сергей Рудаков (fishca) 14.02.12 23:21
Программист предполагает, что после вызова метода строки в нем будут расположены в таком же порядке, как в исходной таблице значений.

Вот сколько пишу на восьмерке, ни разу не предполагал что строки будут расположены в таком же порядке, как в исходной таблице. Где это может понадобиться? Если на порядок закладываешься, то контролируй этот порядок сам.
shiaju; maxis33; AlbinaAAA; Natally_; Yury1001; amiralnar; borman; +7 Ответить 3
2. Осипов Сергей (fixin) 15.02.12 00:08
(1) никогда в отсортированной ТЗ не искал по составному ключу?
3. Misha ⁠ (Magister) 15.02.12 01:17
Я вот уже больше 5 лет с восьмеркой работаю, и тоже никогда не предполагал такого.
(2) А где такое может понадобиться? Если сильно надо что-то найти в большой таблице - делаю через запрос (с использованием временных таблиц).
4. Сергей Ожерельев (Поручик) 15.02.12 01:42
В первый раз слышу про такие предположения и вот сейчас вспоминаю, когда я рассчитывал на порядок строк, где это требовалось и какие меры предпринимались. На ум лезут только запросы с выгрузкой в таблицу значений.
5. Александр Крынецкий (echo77) 15.02.12 07:09
(0) Было бы неплохо получить от автора побликации пример, когда "неправильный" порядок строк в массиве, возвращаемом методом НайтиСтроки может выйти боком.

Первое, что мне пришло на ум, это выбрать строки, а потом удалить их из таблицы. Хотя при последовательно переборе элементов массива и удалением строк из ТЗ методом Удалить(<СтрокаТаблицыЗначений>) все должно пройти корректно.
6. Осипов Сергей (fixin) 15.02.12 07:42
(3) а если в небольшой? Тоже запросом, из пушки по воробьям? Господи, да откройте любую типовую, найдите поиском НайтиСтроки и посмотрите, где этот метод применяется для отсортированной таблицы.
Вообще-то все задачи распределения, партионного списания (не только по товарам, есть задачи списания, где важна последовательность). Короче везде, где НайтиСтроки используется для отсортированной таблицы. У меня - сплошь и рядом.
7. Сергей Ожерельев (Поручик) 15.02.12 08:48
(6) Поискал. 95% использования метода НайтиСтроки - поиск какой-то одной строки, удаление найденных строк, добавление в другую таблицу.
8. Иван Иванов (Famza) 15.02.12 08:54
(6) fixin, да из пушки по воробьям или кувалдой кнопки забивать - без разницы. Вся платформа ориентирована на использование запросов везде и всюду, за исключением записи данных. Так говорится в жкк.
wolfsoft; +1 Ответить
9. Сергей Рудаков (fishca) 15.02.12 09:14
(2) искал, но никогда не загладывался на порядок строк
10. Сергей Кулешов (KulSer) 15.02.12 09:30
(6) fixin.
Если в небольшой, то не проще ли вообще отказаться от стандартного метода НайтиСтроки()? Тупо перебираем строки в исходной таблице, проверяем условие поиска, если Истина, то добавляем найденную строку в результирующую таблицу (или в массив строк, смотря, что нужно получить). Против Ваших двух циклов в процедуре ПослеНайтиСтроки() будет один цикл по исходной таблице.
Вы можете возразить, что если в исходной таблице 10000 строк, а НайтиСтроки() возвращает 10, то два цикла по 10 строк заведомо быстрее одного цикла по 10000 строк. Но я отвечаю конкретно на пост (6), "если в небольшой". А если в "большой", то присоединяюсь к посту (3) "запрос (с использованием временных таблиц)".
Хотя допускаю, что бывают ситуации, когда исходная таблица не мала не велика, и предложенный Вами алгоритм будет оптимальным.
11. Владимир (gfvg) 15.02.12 10:37
Ни разу не встречал чтоб порядок строк в массиве отличался от порядка в ТЗ. Да и код предложенный автором будет вечность работать и применим(?) только для маленьких таблиц. А получать массив отсортированный как ТЗ может очень во многих случаях понадобиться, списание партий/издержек и т.д. Единственное что могу представить, почему у массива порядок строк другой получился, то это проиндексированная ТЗ.
12. Осипов Сергей (fixin) 15.02.12 10:37
(10) а вы замеры сделайте. НайтиСтроки - заточенная под платформу функция, отработает быстрее, чем перебор, неважно, большая таблица или нет.

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

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

(11) а я встречал, да и на партнерском тема тоже озвучена. Индексирование таблицы ускоряет поиск, но может привести к нарушению последовательности строк. Многие даже и не знают о такой фиче.
13. Илья (i132) 15.02.12 14:09
вариант: воспользоваться опертором (ТЗ.)Скопировать(<Строки>, <Колонки>)
Для случая когда известны поля сортировки и не нужна связь с исходной таблицей.

НайдСтроки = ТЗ.НайтиСтроки(Структура);
тз2 = ТЗ.Скопировать(НайдСтроки);
ТЗ2.Сортировать(строкаСортировки);
dj_serega; robix; DrAku1a; Yury1001; fixin; +5 Ответить 2
14. Осипов Сергей (fixin) 15.02.12 16:28
(13) а ты уверен, что он их скопирует в правильном порядке?
это можно проверить, кстати. Если да, то это шикарный метод.
Правда, связь обычно нужна. Для уменьшения остатков партий при списании
15. Илья (i132) 15.02.12 17:27
(14) я не пролистал синтакс-помощник до конца: можно написать еще проще:

тз2 = ТЗ.Скопировать(СтруктураОтбора);
ТЗ2.Сортировать(строкаСортировки)

Циатта из синтакс-Помощника:

Вариант синтаксиса: Скопировать по отбору

Скопировать(<ПараметрыОтбора>, <Колонки>)
Параметры:
<ПараметрыОтбора> (необязательный)
Тип: Структура.
Ключ структуры - идентификатор колонки, а значение структуры - значение отбора.

<Колонки> (необязательный)
Тип: Строка.
Список колонок для копирования в формате: "Колонка1, Колонка2...".

---------------

про порядок строк при копировании нигде не сказано поэтому новую таблицу надо отсортировать по образцу исходной.

---------------
забавный вариант удаления лишних строк из таблицы:
ТЗ=ТЗ.Скоприровать(новый Структура("ИмяКолонки",ЗначениеРеквизита))
16. Осипов Сергей (fixin) 15.02.12 19:44
(15) на сортировку тратится много времени. К тому же сортировка не всегда известна и равна отбору. ТЗ может быть отсортирована ХЗ как.
17. Василий Казьмин (awk) 16.02.12 15:32
(0) Видел в 2007 году в БП 8 глобальную функцию Долги по фифо или как-то так, когда посмотрел на результат, там было что угодно, только не фифо. Полез - использовали именно эту функцию.
18. IR IR (Artemuch2) 16.02.12 16:06
Блин где же вы раньше были то. никак не мог разобраться когда процедура выдает не те результаты что планировал
19. Осипов Сергей (fixin) 16.02.12 16:46
(17)(18) вот видите, а некоторые товарищи в начале говорили, что фигня, все через запросы... А про овраги забыли...
20. vladal (Vladal) 16.02.12 17:05
Неожиданно, я бы сказал "внезапно".

Спасибо за статью, недавно встречал что-то подобное, но плюнул искать. Просто отсортировал ТЗ и всё.
21. Василий Казьмин (awk) 16.02.12 17:42
(19) Это всего лишь показатель квалификации кодеров стандартных конфигураций. Это не проблема для тех, кто читал документацию.
22. Алексей Козаченко (borman) 16.02.12 17:52
Статью следовало озаглавить: "На всякий случай имейте в виду..."
Действительно ни разу не требовалась такая выборка отсортированная определенным образом.
23. Осипов Сергей (fixin) 16.02.12 18:13
(21) не все читают документацию так буквоедически. разумно ожидать от платформы совпадения порядка строк или хотя бы параметра в функции, который бы обеспечивал такой порядок. Такое решение от платформы - прямая неинтуитивная подстава.

(22) ну мало ли что вас еще ждет на длинном жизненном пути...
24. Евгений Игронов (cj512) 16.02.12 18:24
(17)Да даже странно, что в 1с с этим не сталкивались, при чем, что сами так кодят.
Большинство сортировку в запросе отрабатывают.
25. Василий Казьмин (awk) 16.02.12 19:06
(23) Это все равно что говорить: функция с побочным эффектом - подстава. Подстава - это недокументированное поведение.
Например декларируем ФИФО, а реализуем рандом. У меня на поиск ошибки тогда ушло пол дня. На багфикс 1 минута.
26. Осипов Сергей (fixin) 16.02.12 22:42
(24) Когда ты пишешь "большинство", прикладывай пожалуйста, ссылки на исследования, соцопросы и т.п. личный стереотип поведения, возведенный в ранг "большинство" смотрится смешно. просто совет.
(25) все же должны быть какие-то стандарты принятые в отрасли. Еще одной подставой было преобразование в строку по региональным стандартам чисел, а не просто в 232983928392.1234. Это только в 1С так. Есть стандарты в отрасли программирования и их надо соблюдать.
27. Keyfly (Oleg_nsk) 17.02.12 08:16
А разве в синтаксис помощнике говорится, что функция НайтиСтроки что-то там упорядочивает? В описании сказано: "Осуществляет поиск строк таблицы значений, отвечающих заданным условиям поиска". Возвращемое значение: "Массив строк таблицы значений, соответствующих условиям поиска..." Все остальные предположения есть домыслы.
28. Александр Гуляев (gavrikprog) 17.02.12 09:14
Да, если честно для его примера нужен запрос. Тоже никогда не рассчитывал на упорядоченные правильно строки.
Нафиг изобретать велосипеды.
Имхается, что по быстродействию будет тоже самое.

Автор, приведи еще примеры использования...
29. Осипов Сергей (fixin) 17.02.12 10:39
(27) но откуда предположить, что порядок строк при этом меняется, и не такой, как в исходной ТЗ. Однозначно - подстава.
(28) ага, выгружать ТЗ из памяти на сервер, получать обратно запросом по каждому поиску и только для того, чтобы упорядочить строки? Нуну.
30. Илья Олегович Червяков (amiralnar) 17.02.12 12:13
(29) fixin, Я даже предположить не мог, что найденные строки в массиве могут иметь какой-то порядок. Такое свойство у них отсутствует в прикладном и логическом смысле.
Неправильно ты, дядя фиксин, восьмерку ешь. Надо колбасой вниз. Так вкуснее будет.
31. Осипов Сергей (fixin) 17.02.12 13:47
(30) у тебя какое-то нестандартное мышление.
32. Александр Иванов (dkprim) 18.02.12 07:55
хоть опыт работы с 8кой у меня небольшой, но тоже никогда не возникало потребности в том, о чем пишет автор публикации. за информацию, конечно, спасибо. возможно, когда-нибудь потребуется воспользоваться данным методом.. а вообще, запросы люблю юзать :)
33. Осипов Сергей (fixin) 18.02.12 22:09
(32) еще возникнет, я с 1С8 с 2005 года.
34. Владимир Гусев (adhocprog) 18.02.12 23:28
35. Сергей Старых (tormozit) 19.02.12 23:48
Поддерживаю автора. Проблема встречалась мне неоднократно.
36. Осипов Сергей (fixin) 19.02.12 23:51
(35) вот видите. у практиков такая проблема возникает, в отличии от теоретиков, которые якобы запросами пользуются...
37. Илья Олегович Червяков (amiralnar) 20.02.12 04:10
(35) tormozit, Если можете, покажите, пожалуйста, в каком коде вам встречалась эта проблема? Обращались ли вы в 1С с вопросом об обсуждаемом поведении платформы?
38. Сергей Синцов (s.sintsov) 20.02.12 08:23
1C вроде как никому не обещала, что метод найти строки вернет результирующий массив строк в том же порядке, что и исходные строки в таблице. Если на этом не заострили внимание в описании функции, так это только потому, что никто и подумать не мог, что профессиональные программисты будут ожидать от этой функции именно такого поведения. Вы когда-нибудь выборку по SQL таблице делали? Вы что же ожидаете, что результат выборки без дополнительного упорядочивания всегда будет в том же самом порядке, что и исходная таблица? А НайтиСтроки() - это та же самая выборка, только запрос за Вас платформа формирует.
39. Осипов Сергей (fixin) 20.02.12 10:39
(38) вот потому и написана эта статья, что интуитивно ожидается что порядок строк сохранится, а на выходе он получается случайным. Причем в 80% случаев сохраняется а в 20% случайный.
Все фичи 1с знать невозмножно, поэтому эта статья - огромный такой варнинг! ;-)
41. Игор Мудрицкий (Zas1402) 21.02.12 10:38
(13) i132, спасибо очень помогли
42. Александр Капустин (kapustinag) 21.02.12 11:30
(38), (39)
Помнится, когда я начинал работать с СУБД Oracle 20 лет назад, то в руководстве разработчика в самом начале изучения запросов было сказано, что результаты запроса - если не указана сортировка - не обязательно соответствуют физическому порядку строк в таблице. И все, больше никаких вопросов нет.

То есть из-за некачественной документации фирмы 1С и родилась и эта проблема, и дискуссия по ней.
Я согласен, что интуитивно человек ожидает вполне определенную сортировку в данном случае, поэтому, если программа ведет себя не так, поставщик должен был добавить одно предложение в справочную систему, и закрыть вопрос.

Противникам таких "интуитивных ожиданий": конечно, все люди разные, и интуиция у всех по-разному работает. Так в том-то и дело, что можно было бы легко позаботиться обо всех, предупредить их ошибки и проблемы. А можно было...сделать как сделано.
43. Илья (i132) 21.02.12 11:50
Интересно, а откуда вы получаете таблицу значений?, -из запроса? - может быть лучше переписать запрос с итогами - выгружать его в дерево значений или обходить по иерархии.
Работа с деревом будет быстрее если вам надо обработать всю таблицу а не только выбранные строки.
другой вариант получения дерева из таблицы: (с использованием СКД) http://infostart.ru/public/16408/
44. Осипов Сергей (fixin) 21.02.12 12:19
(43) По разному бывает, но гонять ТЗ из памяти на сервер и обратно не вижу смысла. Обработка достаточно нетривиальная всегда в таких случаях в памяти. Мой метод нравится мне больше.
45. Осипов Сергей (fixin) 21.02.12 12:20
(42) повторяю в стопятьсотый раз - эта тема как раз о неинтуитивном моменте в движке 1с. Ибо интуитивно такой фигни ожидать нельзя. У всех интуиция разная, поэтому предупреждаю для тех, кто все же ожидает от 1С сохранения нормального порядка ТЗ - опасайтесь! Для этого и написана статья.
46. Сергей Синцов (s.sintsov) 21.02.12 13:17
(42) Во-во, с документацией у 1С всегда были проблемы, вернее времени на это не оставалось, либо изначально была поставлена задача все тонкости работы платформы объяснять только на учебных курсах.
48. a a (andy2011) 21.02.12 14:20
спасибо очень интересно
49. Maxim Kolkin (the1) 21.02.12 21:12
Надеюсь, в будущих релизах 1С будет гарантировать...

Вот это по-настоящему смешно. Сравните язык 1с8 после языка 1с77, а потом вдумайтесь - будет ли 1С что-либо делать под кодеров.
50. Олег Черкасов (oleg974) 22.02.12 08:41
(1) fishca,
Целиком и полностью поддерживаю. Я тоже всегда контролирую порядок сам...

И хм... может не в тему вопрос. А разве господина Осипова не выгоняли с сайта со скандалом и безвозвратным удалением аккаунта? 0_о
51. Сергей Рудаков (fishca) 22.02.12 09:26
(50)
А разве господина Осипова не выгоняли с сайта со скандалом и безвозвратным удалением аккаунта? 0_о

Доржи объявлял амнистию, теперь фиксин набирает обороты по новой
52. Осипов Сергей (fixin) 22.02.12 10:33
(49) 1с8 по сравнению с 1с7 - шаг вперед. УФ в 1с82 - шаг вбок.
53. Дмитрий Ташланов (Necytij) 23.02.12 11:00
Долго читал тему, и все не могу понять с чего весь сырбор. ну есть проблема, и что? Я тоже никогда не сталкивался, видимо потому что работаю в основном на БП. И надеюсь, как можно меньше людей столкнутся. Но это ведь далеко не самый страшный кошмар от 1Сников. так что никакого "большого варнинга" не вижу...
да и метод, имхо, оставляет желать лучшего.
А почему бы не проставить индексы сначала еще В ТЗ, а потом
ТЗ2 = ТЗ.Скопировать(ТЗ.НайтиСтроки(Структура));
ТЗ2.Сортировать("Индекс");
Это на нескольких отборах, я думаю, хорошо скажется на производительности, да и короче текст намного...
54. Осипов Сергей (fixin) 23.02.12 13:52
(53) надо описывать любые кошмары, большие и маленькие. То, что вы написали, уже предлагали. Иногда важно сохранить ссылки на исходную таблицу для обработки (например уменьшения остатков по партиям).
55. Дмитрий Ташланов (Necytij) 23.02.12 18:31
(16) fixin, (54) fixin,
Да, читал, но быстро запамятовал, просто тут из ничего такую пургу раскрутили, что никак тема из головы моей не выходила, зачем?.
Вы не указали, чем такой метод по-вашему плох.
на сортировку тратится много времени. К тому же сортировка не всегда известна и равна отбору. ТЗ может быть отсортирована ХЗ как.

Что это вообще означает? У вас же точно такая же сортировка...
ТЗ2.Сортировать("Индекс");
М.Очистить();

и при чем тут отбор?
По 54 - кто отменил обращение к таблице по индексу? ТЗ[ТекущаяСтрокаТЗ2.индекс] - чем вам не ссылка на основную строку ТЗ?
Простите, но, по-моему, вы баламут.
56. Осипов Сергей (fixin) 23.02.12 19:55
(55)
Довольно распространенная в моей практике задача - есть большая отсортированная таблица значений, сортировали ее ранее, другими алгоритмами, фиг знает как. Суть не в этом. Я должен выполнить по ней списание по партиям товара из другой ТЗ (просто список товаров), уменьшая количество в этой большой таблице значений.

Перебираю строки маленькой таблицы, нахожу подходящие строки в большой таблице и последовательно списываю.
Если порядок НайтиСтроки нарушается, то возникают проблемы.

А вы о чем, что-то я не понял?
57. Дмитрий Ташланов (Necytij) 23.02.12 20:46
1. Вы сильно преувеличиваете размер проблемы.
2. Вот вы по ТЗ№3 определили что вам в строке Х из ТЗ№2 надо списать Нную сумму, и вы хотите в соответствующей строке ТЗ№1 убрать также Нную сумму. Ну так в строке Х ТЗ№2 есть столбец Индекс, который при обращении к таблице ТЗ№1 по индексу ласт вам ту самую строку:
Х = ТЗ2[5]; //- нужная(в данном конкретном случае именно 6я) строка в маленькой таблице
НужнаяСтрокаБольшойТаблицы = ТЗ[X.Индекс]; //- нужная строка в большой таблице

Вы же свою БОЛЬШУЮ ТЗ№1 не пересортировываете по 100 раз, пока проводите списание и индексы не собьются... так?
58. Осипов Сергей (fixin) 24.02.12 00:50
(57) все зашибись, но про исходный порядок вы забыли. Перебирать найденные строки нужно в том же порядке, что в исходной таблице. Тут простым извлечением индекса не обойдешься, нужна сортировка по индексу.
59. Дмитрий Ташланов (Necytij) 24.02.12 18:08
(58) fixin,
Вы издеваетесь!!!?????
Сначала во всей ТЗ первоначальной проставьте в столбец индекс индекс строки перебором "для инд = 1 по ..."
Потом отбираете строки и сортируете уже новую ТЗ по столбцу индекс!!! Потом когда из строки Х в Табл.значений надо попасть в оригинальную строку вы обращаетесь к строке в ТЗ[СтрокаТаблЗначений2.Индекс].
Сколько раз можно одно и то же писать? Занимаетесь тут маразмом. Не зря вас видать в прошлый раз забанили.
60. Осипов Сергей (fixin) 24.02.12 18:15
(59) я вам объяснял, что порядок сортировки таблицы неизвестен и сортировать не есть хорошее решение. Если не верите, напишите универсальную функцию и объясните, как туда передавать порядок сортировки. Как минимум, эта универсальная функция будет сложнее моей (появится еще один параметр - порядок сортировки) и потребует от программиста больше знаний, нужно еще знать, как отсортирована исходная ТЗ.
К тому же сортировать таблицу по ключам дольше, чем сортировать таблицу по индексу. И копировать всю таблицу дольше, чем копировать индексы. не вижу преимущества вашего подхода.

Вы хоть сто раз 2+2 = 5 напишите, от этого утверждение не станет верным. Попробуйте включить логическое мышление.
61. Дмитрий Ташланов (Necytij) 24.02.12 23:02
Процедура ПередНайтиСтроки(ТЗ)
	ТЗ.КОлонки.Добавить("МойИндекс", НекотореОписаниеОписаниеТипаЧисло);
	для инд = 1 по ТЗ.Количество() цикл
		ТЗ[Инд].МойИндекс = инд;
	конеццикла;
КонецПроцедуры

Функция НайтиСтрокиВТЗ(ТЗ, СтруктураОтбора)
	М = ТЗ.НайтиСтроки(СтруктураОтбора);
	М.Сортировать("МойИндекс");
	Возврат М;
КонецФункции

Процедура Х()
	...
	ПередНайтиСтроки(ТЗ);
	...
	<некий цикл перебора в котором осуществляется последовательная выбора из ТЗ новоявленным методом НайтиСтрокиВТЗ>
	СтруктураОтбора = ...;
	Строки = НайтиСтрокиВТЗ(ТЗ, СтруктураОтбора);
	для инд = 1 по Строки.Количество() цикл    //цикл всего лишь чтобы показать
//как осуществлять обращение к основной ТЗ, вместо того чтобы городить лишнее
		Сообщить("обращение к оригиналу строки № " + строка(инд) + " из " + 
     строка(Строки.Количество()) + " выбранных: " + Строка(ТЗ[Строки[инд].МойИндекс].РеквизитТЗ));
	<конеццикла>
инд = 0;
	для каждого Строка из Строки цикл    //цикл всего лишь чтобы показать
//как осуществлять обращение к основной ТЗ, вместо того чтобы городить лишнее
инд = инд +1;
		Сообщить("обращение к оригиналу строки № " + строка(инд) + " из " + 
    строка(Строки.Количество()) + " выбранных: " + Строка(ТЗ[Строка.МойИндекс].РеквизитТЗ));
	<конеццикла>
	<конеццикла>
КонецПроцедуры
...Показать Скрыть

Проверки синтаксиса нет - писал в блокноте.
При чем тут ваши ключи от квартиры где деньги... - беру ваш пример и убираю оттуда половину текста, оставил лишь образование столбца индекс, но не в выборке, а в основной таблице, и сортировку сразу после выборки. ЭТО ПОЧТИ И ЕСТЬ ВАШ ТЕКСТ! Только без лишнего типа такого:
НСтр.Индекс = ТЗ.Индекс(Эл);

p.s. К тому же привычка называть переменные и процедуры в виде зарезервированных платформой методов, процедур - дурной тон. Иногда можно напороться на неработоспособность куска программы из-за этого. Пару раз допускал такую ошибку, больше не хочется, терять от получаса на такой ерунде.
62. Осипов Сергей (fixin) 25.02.12 10:48
Выражайтесь проще.
Суть вашей мысли - добавить столбец в таблицу, пронумеровать его порядком строк и сортировать по нему найденные строки.
Не забудьте, что у массива (именно его возращает метод НайтиСтроки) нет метода сортировки по колонке, извольте его написать, и чтобы это работало быстрее чем мой метод.
Учитывая, что добавление колонки с индексом и ее заполнение требует некоторых предварительных действий (моя процедура же просто заменяет стандартную), а эффективность не доказана, пока практичная ценность вашего метода еще не доказана.

Повторяю - напишите рабочую функцию в моей обработке, тогда поставим вам ЗАЧЕТ. Но как вариант принимается, правда пока не понятно, хороший ли это вариант...

К тому же, не вижу смысла добавлять колонку индекса, если индекс каждой строки и так можно получить методом Индекс()
63. Дмитрий Ташланов (Necytij) 26.02.12 11:06
(62) fixin,
опечатка - вместо
М = ТЗ.НайтиСтроки(СтруктураОтбора);

то что уже с вами обсуждали:
М = ТЗ.Скопировать(СтруктураОтбора);

Кодить в данном случаем нужно вам - у меня даже нет подходящего набора данных.
64. Осипов Сергей (fixin) 26.02.12 12:15
(63) в структуру отбора нужно добавить еще поле созданного вами индекса
по-прежнему не вижу преимуществ вашего метода. Напишите готовую функцию.
65. Дмитрий Ташланов (Necytij) 26.02.12 12:52
(64) fixin,
точно?
Если указан отбор, то только строки из отбора будут скопированы. Если отбор не указан, то будут скопированы все строки таблицы значений. Если указаны колонки, то только эти колонки будут скопированы. Иначе, будут скопированы все колонки таблицы значений.
У кажете в отбор значение индекса, даже если пустое - максимум что вернет - 1 строку.
66. Дмитрий Ташланов (Necytij) 26.02.12 18:27
Писалось потому что настоящей работой заниматься не хотелось, писал под 8.2.14. Толстый клиент, локальная база. Данные формируются в самой форме обработки - создается таблица на 100,000 строк, в которой в несколько столбцов хранятся числа - остаток от деления на цифры. проц i3 2100. Если кто захочет посмотреть: запускаете, жмете инициализировать, ставите количество проходов, включаете замер в конфигураторе, жмете на кнопку в форме на панели основных действий. Модификация метода заключается в замене ТЗ2 при сортировке отобранных строк на список значений.

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
Прикрепленные файлы:
ВнешняяОбработкаФиксин.epf
67. Илья (i132) 27.02.12 12:51
(61) Necytij, в коде
Функция НайтиСтрокиВТЗ(ТЗ, СтруктураОтбора)
   М = ТЗ.НайтиСтроки(СтруктураОтбора);
   М.Сортировать("МойИндекс");
   Возврат М;
КонецФункции
...Показать Скрыть
у вас ошибка: Найти строки возвращает массив а у массива нет метода сортировать.
Наверно вы имели ввиду
Функция НайтиСтрокиВТЗ(ТЗ, СтруктураОтбора,ИмяКолонкиИндекс)
   ОтобраннаяТЗ = ТЗ.Скопировать(СтруктураОтбора,ИмяКолонкиИндекс);
   ОтобраннаяТЗ.Сортировать(ИмяКолонкиИндекс);
   Возврат ОтобраннаяТЗ;
КонецФункции
...Показать Скрыть

еще можно попробовать неправильный ваиант циклической ссылки - в каждой строке хранить ссылку на саму себя, зато полсе ТЗ.Скопировать(СтруктураОтбора,ИмяКолонкиИндекс+","+ИмяКолонкиССылки) мы получим Таблицу из двух колонок -индекс и ссылка на начальную ТЗ
68. Дмитрий Ташланов (Necytij) 27.02.12 19:09
(67) i132,
Если уж дошли почти до конца топика, то могли прочитать и 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. Жаль что тут спойлеров нет, хоть тот же код прятать.
Morales; i132; +2 Ответить 2
69. Осипов Сергей (fixin) 27.02.12 19:33
(68) включу ваш метод в статью.
Только не понял, что такое методы народ и fixin_мод.
то что fixin - это родной метод, понятно.

Кстати, по замерам - на что больше всего тратится времени?
Можно попробовать выгружать индексы в список и пользоваться методом СортироватьПоЗначению, как вариант.

А что, на получение строки по индексу тратится много времени, что вы для нее колонку создали?
70. Дмитрий Ташланов (Necytij) 27.02.12 22:38
Народ - потому что не этот метод был предложен не только мной.
Модифицированный - читайте 66
Модификация метода заключается в замене ТЗ2 при сортировке отобранных строк на список значений.


Построчно разбирал только свой метод - народ. Корректировал методы заполнения столбца индексами. Большая часть времени? Количество проходов разное. Хотите посмотреть? Скачайте обработку из поста.

Если вы будете сортировать не СортироватьПоЗначению, то кроме индексов у вас там ничего не будет, и чтобы потом заполнить массив, вам придется опять же каждую строку выдергивать из ТЗ по ее индексу из отсортированного списка значений. Я пошел в модифицированном немного другим путем - сделал СортироватьПоПредставлению, где представление - представляет собой индекс. Если бы это было вам интересно, уже бы посмотрели код.
71. Сергей Клевакин (tulaka) 28.02.12 11:18
72. Осипов Сергей (fixin) 28.02.12 11:35
(71) может числовой массив можно как-то по другому отсортировать, тем более что исходный порядок известен.
Может можно обойтись без сортировки?

смотрите, допустим мы получили методом найтистроки строки 12, 10, 45, 38, 41.
Их правильный порядок известен как-бы, ведь есть исходная таблица.
неужели никак нельзя расположить строки в этом порядке?
75. - - (Rebelx) 06.03.12 20:06
Программист предполагает, что после вызова метода строки в нем будут расположены в таком же порядке, как в исходной таблице значений.

Только не очень умный программист так будет предполагать
76. Осипов Сергей (fixin) 07.03.12 10:17
(72) гладко было на бумаге. Вы забыли про время переброса из памяти на сервер и обратно.
(75) рад за вас. я предпочитаю, чтобы неинтуитивные моменты были описаны в документации или исходя из опыта.
77. Misha ⁠ (Magister) 07.03.12 10:34
(6)
Признаюсь, списание по партиям упустил из виду. Но, как тут уже заметили, это вина программистов, которые не читают документацию.
Был забавный случай в УПП для Украины 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С :)
78. Осипов Сергей (fixin) 12.03.12 17:44
(77) статья и признана объяснить одну неочевидную вещь.
79. Dmitriy (daho) 22.03.12 06:56
fixin - давай в том же духе!!! надо ж кому-то этот навоз ворошить... :))) а вообще спасибо, такие фичи знать всегда полезно... вот только хрен их все блин запомнишь....
а программисты бывают не только криворукие, но и пьяные, обкуренные, уставшие, кормящие детей, играющие попутно в квейк и шахматы ну и в конец просто зае%$#ннные чем или кем либо... :)
а талант не пропьешь!!!
80. Павел (MPV) 30.03.12 20:25
Спасибо за информацию. Недавно задумывался как раз над этим вопросом, но лень искать было.
81. Илья (i132) 16.04.12 11:41
Еще пример борьбы с неочевидной сортировкой - сортировка по кнопке сортировать - например если сортировать таблицу по колонке с Значением = const порядок строк поменяется (не надо было сортирровать!)
Вот как можно улучшить кнопку сортировать: http://infostart.ru/public/125020/
82. Илья (i132) 28.04.12 17:44
Про РезультатЗапроса.Выгрузить() в документации тоже не сказано про порядок строк, когда нибудь может перемешать
83. Осипов Сергей (fixin) 03.05.12 10:30
(82) гм, действительно... придется пересортировывать для надежности.
84. Buster 18.05.12 11:49
не имеет никакого смысла использовать эту ерунду. Разве только для того, чтобы замедлить работу программы, а то уж быстро она работает как-то...
При правильном расположении рук возвращается всё в том же порядке, а не в каком-то хаотичном.
Следует не лепить костыли куда попало, а научится писать правильные алгоритмы.
85. Осипов Сергей (fixin) 18.05.12 13:31
86. Юрий Зайцев (Yury1001) 24.05.12 09:11
На днях состряпал отчет с динамическим количеством колонок, использовал СабжМетод с расчетом на правильный (однозначный) порядок результата поиска, т.к. работа бюджетная – заморачиваться не стал, пока всё в порядке. Если для последних релизов (на сегодня 8.2.15) статься справедлива могут перемешаться цифры внутри строк, если что воспользуюсь (13) (15).
87. Осипов Сергей (fixin) 24.05.12 11:49
88. fzt fzt (fzt) 27.05.12 22:53
Улыбнули страсти.
А вот спасибо Автор. Пиши ещё =)
Только что собирался использовать сей метод, решил отгуглить для копипаста, буду иметь ввиду.
Интуитивно ожидал сохранения порядка строк.
Кстати по поводу интуиции. Я это ожидал поскольку много лет работал с кодом, который получает весомый пакет данных. И только апосля упорно с ним работает, сортирует, раскладывает на классификаторы etc. Дело привычки обжувать данные в памяти, нежели тратить ресурсы на запросы к БД. Да и специфика такова, что в момент запроса, БД может физически испариться, я не говорю про возможные блокировки, ожидание в очереди.
То есть алгоритмы поиска придуманные для Я.В.У. почти все гарантируют сохранение порядка строк. Всё-таки непривычно, что 1С по каждому чиху запрос пользует.

P.S. Использовать не буду, но в мемориз покладу.
P.P.S. Товарищи защищавшие писателей справки 1С, ваша въедливость при чтении документации заставляет думать о большом количестве свободного времени. Заведите себе девушку, жену, любовницу или ещё какую личную жизнь. Это когда радуешься НЕ работе ;-). Столько просьб привести примеры из жизни на 1С. Господа, систем под которые пишутся скрипты или бинарный код великое множество. Весьма разнообразные области человеческой деятельности автоматизируются. Если кто-то вынужден въедливо читать документацию на родном мне языке, обдумывая запятые - значит это с системой что-то не так.
89. termit (termit@mail.ru) 18.07.12 10:33
Автор, респект. Подтверждаю: дотачивал обработку "Групповая обработка документов и справочников" в бухгалтерии для госучреждений (скорее всего аналогичное поведение и в стандартной бухгалтерии 2.0) на платформе 8.2
Столкнулся с тем, что после попытки повторно обработать документы они обрабатывались в неправильной последовательности. Массив для обработки там как раз отбирается этой функцией по полю "Пометка" исходной таблицы с отобранными для обработки документами. Стал копать - наткнулся на эту тему.
Так что:
1) люди(в т.ч. программисты 1с, т.к. это их обработка) всё-таки ожидают от этого метода правильный порядок строк
2) тема полезна, автору плюс
90. Михаил Ражиков (tango) 18.07.12 10:38
-: не просто "не тратить время", а вредная статья, курочащая мозги.
впрочем, проголосувавшим - барабан навстречу
91. Осипов Сергей (fixin) 18.07.12 10:49
(90) и в чем же ее вред? в том что показывает неявный глюк 1с?
(89) 1с - не для людей. Даже в документации не предупреждает об этом.
92. Александр Рыжов (AleksR) 12.10.12 14:44
Статья полезная.

Добавьте только в функцию НайтиСтроки() строку:
Возврат М;

Кроме этого, можно было бы в статье написать, что данный способ можно использовать не только для таблиц значений, но и для табличных частей объектов. Только в случае табличной части в функцию ПослеНайтиСтроки() обязательно надо передавать вторым параметром ссылку на табличную часть, так как у её строки нет метода Владелец().
93. Sergey Ivanov (sergb1979) 25.07.13 17:35
При перепродажах использую аналогичное.
Чтобы номера строк не менялись.
94. Serg Morales (Morales) 18.07.14 18:35
(68) Necytij, Спасибо, кратко и понятно, буду использовать
95. Алекс Ю (AlexO) 09.12.14 17:20
(84) Buster,
При правильном расположении рук возвращается всё в том же порядке, а не в каком-то хаотичном.

При каких руках у вас возвращается предсказуемый порядок строк? Т.е. без танцев и бубнов с индексами на обеих берегах выдачи-получения данных вы получаете в результате запроса расположение записей, аналогичное их расположению в БД?
Либо вы открыли недокументированную фишку, которую разработчики БД упустили из виду (сама получилась), либо ничего не поняли из проблемы несинхронности порядка записей при их Создании-Записи-Чтении.
Т.е. проигнорировали саму эту проблему абсолоютно )
96. Алекс Ю (AlexO) 09.12.14 17:25
Если вы предложите более быстрый способ упорядочивания массива найденных строк, буду благодарен.

(69) fixin,
включу ваш метод в статью

И где? ))
И предложили, и благодарность он заслужил, а ты, Сергей, даже обещание не сдержал :)
97. Алекс Ю (AlexO) 09.12.14 17:52
(93) sergb1979,
Чтобы номера строк не менялись.

Каким образом у вас меняются "номера строк", если "номера строк" присваиваются при создании объекта (в данном случае это ТЗ)?
Т.е. как бы вы не тасовали записи, номера строк всегда будут по-порядку и от 1 до n-1 :))
А если имели ввиду "порядок строк", то к номерам строк это отношение не имеет. Точнее, порядок и определяет номера, но не наоборот.
Следовательно, либо вы:
- не писали некий механизм "При перепродажах использую аналогичное"
- не разобрались, как этот механизм "При перепродажах" работает (и обратили внимание совсем не на суть механизма, а на следствие - номера строк)
- не поняли, в чем суть проблемы рассинхронизации порядка.

98. Осипов Сергей (fixin) 10.12.14 10:29
(97) По-моемому в комментариях и статье тема уже достаточно раскрыта. Метод НайтиСтроки может вернуть строки не в том порядке, как они идут в таблице значений. В этом вся суть. Это недокументированная вещь, многим кажется, что порядок должен сохраняться. И это опасно. Об этом статья.
99. Алекс Ю (AlexO) 11.12.14 10:34
(98) тем не менее, именно в комментариях писали и продолжают писать (уже после множества "тема уже достаточно раскрыта") о том, что либо "проблема не существует", либо "да тут все просто, я сто раз уже так делал".
100. Осипов Сергей (fixin) 11.12.14 13:42
101. fzt fzt (fzt) 13.12.14 20:09
(3) Magister, мне похожее понадобилос прямо сейчас, но я порядок не предпологаю. Контролирую.
В запросах тоже порядок не гарантируется, тут уж как индекс на диск положен. ТЗ скармливаю запросу как временную таблицу, мне нужно получить некоторые данные, а совать на вход в запрос все данные из ТЗ - ресурсоёмко, много их. Глупо не оптимально потом построчно проводить поиск между результатом запроса и ТЗ. Менее ресурсоёмко в один проход записать результаты.
Редко, но нужно.

(5) echo77, собственно выше и смежный пример. Есть некая ТЗ, помимо прочих столбцов (с данными) незаполнены артикулы номенклатуры, нужно получить их из справочника. Позиций номенклатуры в ТЗ на порядки меньше количества её в справочнике. Естественно это будет запрос, вот только построчный поиск соответствий - путь низкой квалификации, или раздолбайства (когда время выполнения выходит за разумные пределы).
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа