Функция отбора элементов коллекции быстрым условием

21.08.23

Разработка - Универсальные функции

Функция для компактного вызова отбора элементов коллекции произвольным БЫСТРЫМ (легким) условием

Бесплатные

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Узнавайте о новых бесплатных решениях в нашей телеграм-группе Инфостарт БЕСПЛАТНО

Наименование Скачано Бесплатно
Функция отбора элементов коллекции произвольным условием
.epf 7,96Kb
42 Скачать бесплатно

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

Если это табличная коллекция, то обычно у нее есть метод НайтиСтроки(Структура), позволяющий задать для каждого свойства один элемент отбора на равенство. Для более сложных отборов в таких коллекциях можно применять компоновку данных, которая добавляет ощутимые накладные расходы, но эффективно обрабатывает обращения к БД через точку от ссылки.

Для более сложных отборов в общем случае обычно просто пишем цикл обхода коллекции и добавляем элементы в массив после проверки условия кодом.

Но все эти способы требуют писать относительно много повторяющегося кода.

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

Ближайшее к анонимным функциям, что у нас есть, это метод Выполнить() для выполнения динамического кода. Нам нужно обойти коллекцию и выполнить произвольное быстрое условие-параметр для каждого элемента. Если оно вернет Истина, то добавить элемент в массив результата. Для удобства итератор цикла назовем коротким именем "Э" и предусмотрим необязательные произвольные параметры "П<N>" для использования в условии.

Но большим недостатком метода Выполнить() являются большие накладные расходы на его вызов. Поэтому вызывать его в легком цикле - плохо. Вот почему мы целиком весь цикл сделаем динамическим кодом. Тогда затратный метод Выполнить() мы будет вызывать только один раз. Но для отладки это неудобно. Поэтому предусмотрим и легкую возможность во время отладки переключиться на минимальное использование динамического кода (флаг _РежимОтладки).

// Выбирает в массив данные элементов коллекции произвольным условием.
// Не следует использовать эту функцию для долгих (тяжелых) условий!
// Параметры:
//   Коллекция - Коллекция - произвольная коллекция
//   Условие - Строка - логическое выражение на встроенном языке, где параметр "Э" дает доступ к элементу коллекции, а параметры "П<N>" - к параметрам условия
//   ПутьКСвойству - Строка - путь к свойству, значение которого нужно извлечь из элемента коллекции и добавить в массив результата; если пусто, то добавляется сам элемент; например "ЭлементУправления.ЦветТекста"
//   П1 - Произвольное - параметр "П1" для использования в условии
//   П2 - Произвольное - параметр "П2" для использования в условии
//   П3 - Произвольное - параметр "П3" для использования в условии
// При малом числе элементов заметно медленнее чем статический код. При 100 элементах сопоставима по скорости с ним. При большем числе элементов даже быстрее него.
// Пример: ОтобратьКоллекциюУсловиемЛкс(Коллекция, "Э<>1 И Э<>П1",, Среднее)
// Возвращаемое значение:
//   Массив - элементов коллекции или значений их свойства
Функция ОтобратьКоллекциюУсловиемЛкс(Знач Коллекция, Знач Условие, Знач ПутьКСвойству = "", Знач П1 = 0, Знач П2 = 0, Знач П3 = 0) Экспорт 
	Результат = Новый Массив;  
	_РежимОтладки = Ложь;
	#Если ВебКлиент Или МобильныйКлиент Тогда 
		_РежимОтладки = Истина;
	#ИначеЕсли Не ТонкийКлиент Тогда
		УстановитьБезопасныйРежим(Истина);
	#КонецЕсли
	Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ПрЛкс(_РежимОтладки, 1, 1)     
		// Пассивный оригинал расположенного ниже кода. Выполняйте изменения синхронно в обоих вариантах.
		Для Каждого Э Из Коллекция Цикл
			//Если Э <> 0 Тогда // Для сравнения скорости со статическим кодом
			Если Вычислить(Условие) Тогда
				Результат.Добавить(?(ПустаяСтрока(ПутьКСвойству), Э, Вычислить("Э." + ПутьКСвойству)));
			КонецЕсли; 
		КонецЦикла;
	Иначе
		Попытка
			// Этот вариант кода использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах.
			Выполнить("// ДинамическийКод
			|Для Каждого Э Из Коллекция Цикл
			|	Если " + Условие + " Тогда
			|		Результат.Добавить(Э" + ?(ПустаяСтрока(ПутьКСвойству), "", "." + ПутьКСвойству) + ");
			|	КонецЕсли; 
			|КонецЦикла;");
		Исключение
			Ошибка = ОбработатьИсключениеВДинамическомКодеЛкс(ИнформацияОбОшибке());
			Если ЗначениеЗаполнено(Ошибка) Тогда
				ВызватьИсключение Ошибка;
			Иначе
				ВызватьИсключение;
			КонецЕсли;
		КонецПопытки;
	КонецЕсли;
	Возврат Результат;  

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

// Обход ошибки платформы в обычном клиентском приложении https://www.hostedredmine.com/issues/965445
// Позволяет перевыбросить исключение так, чтобы конфигуратор позволял быстрый переход к ближайшей строке статического кода из ошибки в динамическом коде.
// Динамический код должен начинаться с "// ДинамическийКод"
Функция ОбработатьИсключениеВДинамическомКодеЛкс(ИнформацияОбОшибке) Экспорт 
	
	#Если Сервер И Не Сервер Тогда
		ИнформацияОбОшибке = ИнформацияОбОшибке();
	#КонецЕсли
	Результат = Неопределено;
	Если Ложь
		Или ИнформацияОбОшибке.Причина = Неопределено 
		Или Найти(ИнформацияОбОшибке.Описание, "Ошибка компиляции") > 0
	Тогда
		Ошибка = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
		Позиция = Найти(Ошибка, "// ДинамическийКод");
		Если Позиция > 0 Тогда
			Результат = Лев(Ошибка, Позиция - 1);
		КонецЕсли;  
	КонецЕсли;
	Возврат Результат;

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

// Присваивает первому параметру второй.
// Удобно вызывать из отладчика через диалог "Вычислить выражение" (в 8.3 есть встроенный аналог) или в условной точке останова для модификации значения переменной без остановки.
// Параметры:
//  П1           - Произвольный - Указатель на переменную, которой присваиваем значение;
//  П2           - Произвольный - значение, которое присваиваем;
//  ВернутьЛожь  - Булево - если включено, то функция возвращает Ложь, что необходимо для использования в точке останова
//
// Возвращаемое значение:
//  Значение параметра П1 после присвоения, либо Ложь.
//
Функция ПрЛкс(п1, Знач п2 = Неопределено, Знач ВернутьЛожь = Ложь) Экспорт
    п1 = п2;
    Если ВернутьЛожь Тогда
        Возврат Ложь; // Чтобы в точке останова использовать
    Иначе
        Возврат п1;
    КонецЕсли;
КонецФункции

Вспомогательная функция ОбработатьИсключениеВДинамическомКодеЛкс нужна чтобы обойти жестокое удаление платформой связи с исходной строкой модуля в описании ошибки в обычном приложении.

Вспомогательная функция ПрЛкс нужна для автоматической установки флага _РежимОтладки в условной точке останова при каждом выполнении главной функции.

Все функции доступны в тонком клиенте.

 

Пример 1

Нужно отобрать из таблицы описания структуры хранения базы данных только строки описания таблиц табличных частей справочников

Сначала запишет традиционным полностью статическим кодом

Коллекция = ПолучитьСтруктуруХраненияБазыДанных();
Строки = Новый Массив;
Для Каждого Э Из Коллекция Цикл
	Если Найти(Э.Метаданные, "Справочник") И Найти(Э.Метаданные, "ТабличнаяЧасть") Тогда
		Строки.Добавить(Э);
	КонецЕсли;
КонецЦикла;
Таблица = Коллекция.Скопировать(Строки);

А теперь запишем через нашу функцию

Коллекция = ПолучитьСтруктуруХраненияБазыДанных();
Строки = ОтобратьКоллекциюУсловиемЛкс(Коллекция, "Найти(Э.Метаданные, П1) И Найти(Э.Метаданные, П2)",, "Справочник", "ТабличнаяЧасть");
Таблица = Коллекция.Скопировать(Строки);

Компактность заметно повысилась, т.к. количество строк сократилось с 6 до 1. Но также можно отметить небольшое снижение читаемости, что для простых условий не играет большой роли.

 

Недостатки

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

Однако в процессе редактирования можно пойти на небольшую хитрость и временно делать этот код статическим. Тогда для него будут работать помощники ввода.

Рассмотрим другой пример. Тут мы выбираем из списка значений только элементы с пометкой и значением больше 3. Перед вызовом нашей функции вставим вспомогательную инструкцию для обозначения типа итератора "Э", используемого в условии. Для остальных параметров, задействованных в условии писать такие инструкции не придется, если давать им в текущем контексте те же имена, что и в условии.

Пример 2

Коллекция = Новый СписокЗначений;
Для Счетчик = 1 По 10 Цикл
	Коллекция.Добавить(Счетчик,, Счетчик % 2 = 0);  
КонецЦикла;
П1 = Новый Структура("Предел", 3);
#Если Сервер И Не Сервер Тогда
	Э = Коллекция[0];
#КонецЕсли
ф = ОтобратьКоллекциюУсловиемЛкс(Коллекция, "Э.Пометка И Э.Значение > П1.Предел ",, П1);

Теперь при редактировании временно удаляем начальный символ "двойная кавычка" и у нас начинают работать все помощники ввода в коде условия. Забыть вернуть обратно ее мы не сможем, т.к. будет ошибка компиляции модуля из-за конечной кавычки.

 

 

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

При малом числе элементов выполнение этой функции медленнее чем полностью статический код из-за накладных расходов на единственный вызов Выполнить(). При 100+ элементах разница уже исчезает и дальше смещается в другую сторону.

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

Короткие примеры

ИменаВидимыхКолонок = ОтобратьКоллекциюУсловиемЛкс(ТабличноеПоле.Колонки, "Э.Видимость И Не ПустаяСтрока(Э.Данные)", "Данные");
КолонкиВложенныхТаблиц = ОтобратьКоллекциюУсловиемЛкс(Колонки, "Э.ТипЗначения.СодержитТип(П1)", "Имя", Тип("РезультатЗапроса"));
СтрокиОдноименных = ОтобратьКоллекциюУсловиемЛкс(КоллекцияСтрок, "Э.Ключ = П1",, ТекущийПсевдоним);
СтрокиОдноименных = ОтобратьКоллекциюУсловиемЛкс(КоллекцияСтрок, "Э.Представление = П1",, ТекущийПсевдоним);
СтрокиОдноименных = ОтобратьКоллекциюУсловиемЛкс(КоллекцияСтрок, "Э.Имя = П1",, ТекущийПсевдоним);
КопияПорядка = ОтобратьКоллекциюУсловиемЛкс(НастройкаКомпоновки.Порядок.Элементы, "Э.Использование");
УдаляемыеКлючи = ОтобратьКоллекциюУсловиемЛкс(СтруктураКлюча, "ТипЗнч(Э.Значение) = П1", "Ключ", Тип("ОписаниеТипов"));
ЧислоНевидимых = ОтобратьКоллекциюУсловиемЛкс(ЭлементыФормы.ДинамическийСписок.Колонки, "Не Э.Видимость ").Количество();
ЧислоНевидимых = ОтобратьКоллекциюУсловиемЛкс(фОбъект.НастройкиКолонок, "Не Э.Видимость ").Количество();
Результат = ОтобратьКоллекциюУсловиемЛкс(МетаданныеДляРегистрации, "Э.Регистрировать", "ОбъектДляРегистрации");
СтрокиКУдалению = ОтобратьКоллекциюУсловиемЛкс(ДеревоТаблиц.Строки, "Э.Строки.Количество() = 0");
НепустыеСсылки = ОтобратьКоллекциюУсловиемЛкс(Расходы, "ЗначениеЗаполнено(Э.Рейс)", "Рейс");

Демо внешняя обработка

К статье приложена внешняя обработка со всеми функциями и примерами использования.

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

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

14.05.2025    5404    DeerCven    15    

57

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

21.05.2024    46312    dimanich70    83    

164

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    6845    6    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    57357    atdonya    31    

68

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    8609    ke.92@mail.ru    17    

68

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    22761    YA_418728146    8    

174
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. fatman78 21 24.06.23 21:14 Сейчас в теме
Спасибо Сергей. Как раз то, что надо... Отлично подойдет для таблиц значений где "НайтиСтроки" уже мало из-за ограничений отбора на равенство, а комбайн "компоновки данных" заводить не хочется...

P.S. в статье пропущено "не" в предложении "А у нас вроде бы пока ничего удобного появлялось."
2. mszsuz 345 25.06.23 05:34 Сейчас в теме
Спасибо за статью, теперь я точно знаю, что если бы и пришла в голову такая идея, то так делать не стоит.
К недостаткам ещё стоит добавить потерю прозрачности замера производительности и невозможность поставить точку останова в цикле перебора.
konstsv; dima_gsv; +2 Ответить
3. tormozit 7324 25.06.23 08:03 Сейчас в теме
(2)
потерю прозрачности замера производительности и невозможность поставить точку останова в цикле перебора

Видимо ты невнимательно читал статью. Я там писал, что в функции предусмотрен внутренний флаг _РежимОтладки (замедленный режим ее работы), который позволяет поставить точку останова на любом проходе цикла и более детально замерить производительность.
Если представить что в платформе бы появились лямбда-выражения, то допускаю что эти недостатки бы не исчезли и возможно даже усилились по отношению к _РежимОтладки, т.к. платформа не позволяет ставить точку останова внутри инструкции кода и дробить ее в замере производительности.
4. mszsuz 345 25.06.23 08:21 Сейчас в теме
(3) Видел. Получается я, например, делаю замер открытия формы, вижу что тормозит "лучший код", который вызывается 20 раз из разных мест, должен поставить в ней точку останова, снова запустить замер и 20 раз поменять режим отладки? И всё это ради экономии нескольких строчек кода?
5. tormozit 7324 25.06.23 08:44 Сейчас в теме
(4) В строке кода
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ПрЛкс(_РежимОтладки, 1, 1) 

Указан поясняющий комментарий. Он подсказывает, что можно создать условную точку останова для автоматической установки флага _РежимОтладки при каждом выполнении этой строки кода. Для этого нужна вспомогательная функция на подобие
// Присваивает первому параметру второй.
// Удобно вызывать из отладчика через диалог "Вычислить выражение" (в 8.3 есть встроенный аналог) или в условной точке останова для модификации значения переменной без остановки.
// Параметры:
//  П1           - Произвольный - Указатель на переменную, которой присваиваем значение;
//  П2           - Произвольный - значение, которое присваиваем;
//  ВернутьЛожь  - Булево - если включено, то функция возвращает Ложь, что необходимо для использования в точке останова
//
// Возвращаемое значение:
//  Значение параметра П1 после присвоения, либо Ложь.
//
Функция ПрЛкс(п1, Знач п2 = Неопределено, Знач ВернутьЛожь = Ложь) Экспорт
	п1 = п2;
	Если ВернутьЛожь Тогда
		Возврат Ложь; // Чтобы в точке останова использовать
	Иначе
		Возврат п1;
	КонецЕсли;
КонецФункции
Показать

Добавил эту функцию в статью.
Аналогичный прием активно применяет в методике однострочного кода https://infostart.ru/1c/articles/1732527/
sulfur17; +1 Ответить
23. sulfur17 70 26.06.23 09:54 Сейчас в теме
(5)
Функция ПрЛкс(п1, Знач п2 = Неопределено, Знач ВернутьЛожь = Ложь) Экспорт
п1 = п2;
Если ВернутьЛожь Тогда
Возврат Ложь; // Чтобы в точке останова использовать
Иначе
Возврат п1;
КонецЕсли;
КонецФункции


это же гениально!))
А зачем может понадобиться вызывать функцию с ВернутьЛожь = Ложь?
Я вообще правильно понял - это функция нужна чтобы включить режим отладки не обновляя конфигурацию?
25. tormozit 7324 26.06.23 11:58 Сейчас в теме
(23) Функция ПрЛкс принадлежит условному виду функций "Функции режима отладки". Основная задачи функции ПрЛкс - присвоение значения свойству/переменной в точке останова. Параметр п1 передается по ссылке, т.к. присвоение может выполняться свойству объекта с ограничениями типа. Поэтому важно прямо в окне "Вычислить выражение" сразу понять, какое значение установилось в это свойство. Для этого функция по умолчанию возвращает значение установленного свойства.
Подробнее о функциях режима отладки можно узнать из специальной формы подсистемы ИР https://www.hostedredmine.com/issues/928281
sulfur17; +1 Ответить
17. tormozit 7324 25.06.23 16:55 Сейчас в теме
(4) Дописал в статье про вред для долгих условий и в целом сделал бОльший акцент на быстрых условиях.
Не следует использовать эту функцию для возможно долгих (тяжелых) условий особенно если они обращаются к БД, т.к. замер производительности будет привязывать выполнения всех различных условий к одной строке статического кода этой функции и будет сложно понять, какие конкретно условия дают большУю длительность. Тут уместна аналогия с вредом от выполнения различных запросов через единую функцию - замер производительности покажет что значительное время заняла строка выполнения запроса в этой функции, но понять какие именно запросы внесли наибольший вклад, будет очень сложно без техножурнала.
6. PerlAmutor 160 25.06.23 10:04 Сейчас в теме
В статье написано "Выполнить()", а в коде используется "Вычислить()" (и Выполнить() отсутствует в Web-клиенте, что может ввести читателей статьи в заблуждение). Ну и Вычислить() - "В режимах запуска мобильного приложения метод не поддерживается в операционной системе iOS"
В ЯВУ таких как C++ все это дело называется Comparator. Там обычно передается указатель на функцию-компаратор в метод коллекции для сортировки например.

Ну и предусмотреть включение безопасного режима хорошо бы https://its.1c.ru/db/v8std#content:770:hdoc
7. tormozit 7324 25.06.23 10:22 Сейчас в теме
(6) В статье указана доступность функции для тонкого клиента, а не для веб и не для мобильного клиентов. Для них я не планирую поддерживать работу функции, но сделать это несложно - просто включать флаг _РежимОтладки.

Про функцию-параметр - решение очевидное, но заметно менее компактное и менее быстрое, т.к. функция будет вызываться для каждого элемента. Поэтому если условие отбора само компактное, то ради его передачи в качестве параметра - создавать функцию и описывать ее параметры - менее неудобно и замедлит работу для больших коллекций. Кстати в мою функцию передать функцию-параметр, вычисляющую условие тоже можно
ОтобратьКоллекциюУсловиемЛкс(Коллекция, "Условие1(Э,А)",, Среднее)
Функция Условие1(Элемент, Порог)
     Возврат Элемент > Порог;
КонецФункции

Преимущества здесь следуют из статической компиляции - легче отлаживать, замерять производительность, обеспечивать безопасность.
10. tormozit 7324 25.06.23 11:04 Сейчас в теме
(6) Включение безопасного режима добавил
8. PerlAmutor 160 25.06.23 10:31 Сейчас в теме
Кстати, если для проверки кода используете EDT, то рекомендую эту конструкцию таким образом записывать, чтобы уменьшить количество ложных срабатываний проверки на ошибки:

	#Если Сервер И Не Сервер Тогда //@skip-check code-never-compilied
		ИнформацияОбОшибке = ИнформацияОбОшибке();
	#КонецЕсли


P.S.: похоже разработчики EDT допустили орфографическую ошибку в слове "compilied", там видимо должно быть написано "compiled"
13. tormozit 7324 25.06.23 14:25 Сейчас в теме
(8) Это далеко от темы этой статьи, зато намного ближе к теме другой статьи на которую я тут указывал ссылку. Полезнее это написать там.
9. SeiOkami 3606 25.06.23 10:49 Сейчас в теме
Основное преимущество linq в том, чтобы оно проверялось на уровне компилятора. Тогда выходит не только короче, но и безопаснее. Проще не только писать, но и находить ошибки и поддерживать.

Не хватает поддержки на уровне платформы=(
11. пользователь 25.06.23 13:50
Сообщение было скрыто модератором.
...
12. пользователь 25.06.23 14:06
Сообщение было скрыто модератором.
...
16. пользователь 25.06.23 15:52
Сообщение было скрыто модератором.
...
14. пользователь 25.06.23 15:30
Сообщение было скрыто модератором.
...
15. пользователь 25.06.23 15:50
Сообщение было скрыто модератором.
...
18. MIracloid2000 25.06.23 23:06 Сейчас в теме
К сожалению, статические анализаторы кода не смогут понять код такого условия.


очень похоже на то, что я на них похож... статья о чем?
Andreyyy; CK3; +2 1 Ответить
19. caponid 26.06.23 00:35 Сейчас в теме
В режиме отладки не проще ли записать вместо
Вычислить("Э." + ПутьКСвойству)

просто
Э[ПутьКСвойству]
20. tormozit 7324 26.06.23 00:38 Сейчас в теме
(19) Сначала так и было. Но иногда нужно и через точку брать свойство, о чем написано в описании параметра.
21. caponid 26.06.23 00:55 Сейчас в теме
(20) может быть.. но на вскидку мне почему то такие ситуации "не моделируются".

а так имхо впечатление скорее отрицательное

если нужна наглядность и "воздушность" в отборах, то лучше использовать fluent подход - есть такие библиотеки - из оперы ооп (обработко ориентированный подход:)...
если скорость и опять же наглядность - то написать десяток строк кода, оформленных в отдельную функцию отбора...

вобщем меня мучают сомнения)
22. tormozit 7324 26.06.23 08:20 Сейчас в теме
(21)
если нужна наглядность и "воздушность" в отборах

Вроде бы я не обозначал такой цели, а обозначал цель "компактность".
то лучше использовать fluent подход

fluent это про экономию текста в последовательности выполнения операций над одним объектом. А эта статья про одну операцию.
24. 0x00 26.06.23 10:11 Сейчас в теме
Из недостатков метода можно отметить практическую невозможность его использования в технологии сервиса, где методы Выполнить() и Вычислить() запрещены https://1cfresh.com/articles/so_addprocess_fastaudit#:~:text=%D0%92%C2%A0%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%­D0%BD%D0%BE%D0%BC%20%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B5%20%­D0%B7%D0%B0%D0%BF%D1%80%D0%B5%D1%89%D0%B5%D0%BD%D1%8B,%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%BE%D0%B2%20%D0%92%D1%8B%D0­%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D1%8C()%20%D0%B8%C2%A0%D0%92%D1%8B%D1%87%D0%B8%D1%81%D0%BB%D0%B8%D1­%82%D1%8C()

Если просто относительно подхода, то я бы использовал отбор в запросе (что, конечно, имеет свои ограничения)
26. tormozit 7324 26.06.23 12:02 Сейчас в теме
(24) Запрос нельзя использовать для отбора элементов коллекций, содержащих неподдерживаемые запросом типы значений, а их очень немного. Зато можно использовать компоновку данных.
27. tormozit 7324 26.06.23 13:22 Сейчас в теме
(26) Уточнение. Типов значений, поддерживаемых запросами, очень немного. В объектной модели из значительно больше.
28. 0x00 26.06.23 16:23 Сейчас в теме
(27) Конечно, именно поэтому я и упомянул про ограничения) В моей практике запрос можно использовать в 80% случаев, что, конечно, обусловлено моей специализацией, и, скорее всего, у других это не так.
29. triviumfan 102 26.06.23 19:30 Сейчас в теме
За новизну, универсальность и смелость, однозначно, плюс.
С виду лаконичная и универсальная, но я боюсь её использовать, лучше по-старинке в цикле или запросом отберу :)
30. kser87 2480 26.06.23 20:29 Сейчас в теме
Интересная мысль. Но код делает непонятнее
dima_gsv; +1 Ответить
31. tormozit 7324 26.06.23 22:02 Сейчас в теме
(30) А лямбда-выражения в других языках делают его понятнее?
32. ubnkfl 26.06.23 23:06 Сейчас в теме
(31) Для рядового 1Сника точно не делают )). Тут еще убогость конфигуратора играет роль. После условного VS code с разноцветной подсветкой скобок и кучей плагинов для форматирования кода - вручную такие выражения городить и читать в 1С неудобно.
33. kalyaka 1138 07.07.23 11:18 Сейчас в теме
целиком весь цикл сделаем динамическим кодом
Отличная идея! Попробую в будущих версиях реализации абстрактного массива.
С абстрактным массивом код может быть такой:
Коллекция = ПолучитьСтруктуруХраненияБазыДанных();
Строки = РаботаСМассивом.АТДМассив(Коллекция)
    .Отобрать("СтрНайти(Элемент.Метаданные, 'Справочник') > 0 И СтрНайти(Элемент.Метаданные, 'ТабличнаяЧасть') > 0")
    .ВМассив()
;
Для Каждого Строка Из Строки Цикл
    Сообщить(Строка.Метаданные);
КонецЦикла;
34. tormozit 7324 21.08.23 16:11 Сейчас в теме
Еще один частый случай, где функцию эффективна - отбор только заполненных значений. Например надо отобрать только заполненные ссылки документов из колонки таблицы.
ОтобратьКоллекциюЛкс(Расходы, "ЗначениеЗаполнено(Э.Рейс)", "Рейс")
35. It-developer 27 09.11.23 14:55 Сейчас в теме
Спасибо! Отличные разработки для работы - добавлю в свой модуль работы с коллекциями.
Поменял бы названия функций.
Есть вопрос - Лкс - что означает аббревиатура?
36. It-developer 27 09.11.23 14:58 Сейчас в теме
В моей примере - обратный цикл: код с 7 строк стал 2-х строчным, но 1 из строк стала довольно длинной.
Но, как по мне, читаемость стала лучше

Было:
к  = тРезультат.Количество() - 1;
Пока к >= 0 Цикл
	Если тРезультат[к].КоличествоВРаботу / КоличествоМоделейВОдномНастиле = Цел(тРезультат[к].КоличествоВРаботу / КоличествоМоделейВОдномНастиле) Тогда
		тРезультат.Удалить(к);
	КонецЕсли;	
	к = к - 1;
КонецЦикла;	


Стало:
[1C-CODE]Строки = ОтобратьКоллекциюУсловиемЛкс(тРезультат, 
	"(Э.КоличествоВРаботу / КоличествоМоделейВОдномНастиле) <> Цел(Э.КоличествоВРаботу / КоличествоМоделейВОдномНастиле)",,
	"КоличествоМоделейВОдномНастиле" = КоличествоМоделейВОдномНастиле);
	тРезультат = тРезультат.Скопировать(Строки);
[/1C-CODE]
37. tormozit 7324 04.01.24 07:36 Сейчас в теме
Сделал в ИР контекстную подсказку для редактирования условия отбора прямо в строковом литерале. Она привязывается к имени метода https://www.hostedredmine.com/issues/977735 . Вместе с ИР адаптером для TurboConf будет работать и в конфигураторе.
Для отправки сообщения требуется регистрация/авторизация