//////////////////////////////////////////////////////////////////////////////// // Модуль: A1sDS // Назначение: Упрощённая работа со структурами и парами ключ-значение // Версия: 1.0.0 // Автор: A1sCode // Сайт: https://a1scode.ru // Лицензия: MIT // Совместимость: 1С:Предприятие 8.3+ //////////////////////////////////////////////////////////////////////////////// // // Создает структуру из произвольного количества пар ключ-значение (до 20). ✦ // Первый ключ ➤ // Первое значение ➤ // Второй ключ ➤ // Второе значение ➤ // Третий ключ ➤ // Третье значение ➤ // Четвертый ключ ➤ // Четвертое значение ➤ // Пятый ключ ➤ // Пятое значение ➤ // Шестой ключ ➤ // Шестое значение ➤ // Седьмой ключ ➤ // Седьмое значение ➤ // Восьмой ключ ➤ // Восьмое значение ➤ // Девятый ключ ➤ // Девятое значение ➤ // Десятый ключ ➤ // Десятое значение ➤ // Structure — новая структура с переданными парами ⬅ // // // // A1sDS.Of("name", "John", "age", 30) -> {name: "John", age: 30} // // A1sDS.Of("x", 10, "y", 20, "color", "red") -> {x: 10, y: 20, color: "red"} // // Функция Of( Ключ1 = Неопределено, Знач1 = Неопределено, Ключ2 = Неопределено, Знач2 = Неопределено, Ключ3 = Неопределено, Знач3 = Неопределено, Ключ4 = Неопределено, Знач4 = Неопределено, Ключ5 = Неопределено, Знач5 = Неопределено, Ключ6 = Неопределено, Знач6 = Неопределено, Ключ7 = Неопределено, Знач7 = Неопределено, Ключ8 = Неопределено, Знач8 = Неопределено, Ключ9 = Неопределено, Знач9 = Неопределено, Ключ10 = Неопределено, Знач10 = Неопределено, Ключ11 = Неопределено, Знач11 = Неопределено, Ключ12 = Неопределено, Знач12 = Неопределено, Ключ13 = Неопределено, Знач13 = Неопределено, Ключ14 = Неопределено, Знач14 = Неопределено, Ключ15 = Неопределено, Знач15 = Неопределено, Ключ16 = Неопределено, Знач16 = Неопределено, Ключ17 = Неопределено, Знач17 = Неопределено, Ключ18 = Неопределено, Знач18 = Неопределено, Ключ19 = Неопределено, Знач19 = Неопределено, Ключ20 = Неопределено, Знач20 = Неопределено ) Экспорт //⚙ ib = "Создание структуры из пар ключ-значение"; //✍ Структура = Новый Структура(); //✏ Если ТипЗнч(Ключ1) = Тип("Строка") Тогда Структура.Вставить(Ключ1, Знач1); КонецЕсли; Если ТипЗнч(Ключ2) = Тип("Строка") Тогда Структура.Вставить(Ключ2, Знач2); КонецЕсли; Если ТипЗнч(Ключ3) = Тип("Строка") Тогда Структура.Вставить(Ключ3, Знач3); КонецЕсли; Если ТипЗнч(Ключ4) = Тип("Строка") Тогда Структура.Вставить(Ключ4, Знач4); КонецЕсли; Если ТипЗнч(Ключ5) = Тип("Строка") Тогда Структура.Вставить(Ключ5, Знач5); КонецЕсли; Если ТипЗнч(Ключ6) = Тип("Строка") Тогда Структура.Вставить(Ключ6, Знач6); КонецЕсли; Если ТипЗнч(Ключ7) = Тип("Строка") Тогда Структура.Вставить(Ключ7, Знач7); КонецЕсли; Если ТипЗнч(Ключ8) = Тип("Строка") Тогда Структура.Вставить(Ключ8, Знач8); КонецЕсли; Если ТипЗнч(Ключ9) = Тип("Строка") Тогда Структура.Вставить(Ключ9, Знач9); КонецЕсли; Если ТипЗнч(Ключ10) = Тип("Строка") Тогда Структура.Вставить(Ключ10, Знач10); КонецЕсли; Если ТипЗнч(Ключ11) = Тип("Строка") Тогда Структура.Вставить(Ключ11, Знач11); КонецЕсли; Если ТипЗнч(Ключ12) = Тип("Строка") Тогда Структура.Вставить(Ключ12, Знач12); КонецЕсли; Если ТипЗнч(Ключ13) = Тип("Строка") Тогда Структура.Вставить(Ключ13, Знач13); КонецЕсли; Если ТипЗнч(Ключ14) = Тип("Строка") Тогда Структура.Вставить(Ключ14, Знач14); КонецЕсли; Если ТипЗнч(Ключ15) = Тип("Строка") Тогда Структура.Вставить(Ключ15, Знач15); КонецЕсли; Если ТипЗнч(Ключ16) = Тип("Строка") Тогда Структура.Вставить(Ключ16, Знач16); КонецЕсли; Если ТипЗнч(Ключ17) = Тип("Строка") Тогда Структура.Вставить(Ключ17, Знач17); КонецЕсли; Если ТипЗнч(Ключ18) = Тип("Строка") Тогда Структура.Вставить(Ключ18, Знач18); КонецЕсли; Если ТипЗнч(Ключ19) = Тип("Строка") Тогда Структура.Вставить(Ключ19, Знач19); КонецЕсли; Если ТипЗнч(Ключ20) = Тип("Строка") Тогда Структура.Вставить(Ключ20, Знач20); КонецЕсли; Возврат Структура; //↩ КонецФункции // // Создает пару ключ-значение в виде структуры с полями Ключ и Значение. ✦ // Ключ пары ➤ // Значение пары ➤ // Structure — структура пары с полями Ключ и Значение ⬅ // // // // A1sDS.Pair("name", "John") -> {Ключ: "name", Значение: "John"} // // Функция Pair(Key, Value) Экспорт //⚙ ib = "Создание пары ключ-значение"; //✍ Возврат Новый Структура("Ключ, Значение", Key, Value); //↩ КонецФункции // // Создает структуру из массива пар, где каждая пара — структура с полями Ключ и Значение. ✦ // Массив пар-структур ➤ // Structure — новая структура ⬅ // // // // pairs = A1sAR.Of(A1sDS.Pair("x", 10), A1sDS.Pair("y", 20)); // // A1sDS.OfPairs(pairs) -> {x: 10, y: 20} // // Функция OfPairs(Пары) Экспорт //⚙ ib = "Создание структуры из массива пар"; //✍ Структура = Новый Структура(); //✏ Для Каждого Пара Из Пары Цикл //⟳ Структура.Вставить(Пара.Ключ, Пара.Значение); //✏ КонецЦикла; Возврат Структура; //↩ КонецФункции // // для создания структуры из плоского массива пар [ключ1, значение1, ключ2, значение2]. ✦ // Плоский массив пар ключ-значение ➤ // Structure — структура ⬅ // // Функция Struct(ПлоскийМассивПар) Экспорт //⚙ ib = "для создания структуры из плоского массива пар"; //✍ Пары = Новый Массив(); //✏ Счет = 0; //✏ Пока Счет < ПлоскийМассивПар.Количество() - 1 Цикл //⟳ Пары.Добавить(Pair(ПлоскийМассивПар[Счет], ПлоскийМассивПар[Счет + 1])); //▶️ Счет = Счет + 2; //✏ КонецЦикла; Возврат OfPairs(Пары); //▶️ КонецФункции // // Создает структуру из строки ключей и массива значений. ✦ // Строка ключей через запятую ➤ // Массив значений в том же порядке ➤ // Structure — новая структура ⬅ // // // // A1sDS.OfKeysAndValues("name,age,city", A1sAR.Of("John", 30, "NYC")) // // -> {name: "John", age: 30, city: "NYC"} // // Функция OfKeysAndValues(Keys, Values) Экспорт //⚙ ib = "Создание структуры из ключей и значений"; //✍ МассивКлючей = СтрРазделить(Keys, ","); //✏ Результат = Новый Структура(); //✏ Для i = 0 По Мин(МассивКлючей.Количество(), Values.Количество()) - 1 Цикл //⟳ Ключ = СокрЛП(МассивКлючей[i]); //✏ Если ЗначениеЗаполнено(Ключ) Тогда //⚡ Результат.Вставить(Ключ, Values[i]); //✏ КонецЕсли; КонецЦикла; Возврат Результат; //↩ КонецФункции // // Создает структуру из строки вида "Ключ=Значение, Ключ2=Значение2". ✦ // Строка пар ключ=значение через запятую ➤ // Structure — новая структура ⬅ // // // // A1sDS.OfString("name=John, age=30") -> {name: "John", age: "30"} // // Функция OfString(Строка) Экспорт //⚙ ib = "Создание структуры из строки"; //✍ Результат = Новый Структура(); //✏ Пары = СтрРазделить(Строка, ","); //✏ Для Каждого Пара Из Пары Цикл //⟳ ЧастиПары = СтрРазделить(Пара, "="); //✏ Если ЧастиПары.Количество() = 2 Тогда //⚡ Ключ = СокрЛП(ЧастиПары[0]); //✏ Значение = СокрЛП(ЧастиПары[1]); //✏ Результат.Вставить(Ключ, Значение); //✏ КонецЕсли; КонецЦикла; Возврат Результат; //↩ КонецФункции // // Создает структуру из QueryString (URL параметров): "name=John&age=30". ✦ // Строка параметров URL ➤ // Structure — структура с параметрами ⬅ // // // // A1sDS.OfQueryString("name=John&age=30&city=New%20York") // // -> {name: "John", age: "30", city: "New York"} // // Функция OfQueryString(QueryString) Экспорт //⚙ ib = "Разбор QueryString в структуру"; //✍ Результат = Новый Структура(); //✏ Параметры = СтрРазделить(QueryString, "&"); //✏ Для Каждого ПараметрСтрока Из Параметры Цикл //⟳ Пара = СтрРазделить(ПараметрСтрока, "="); //✏ Если Пара.Количество() = 2 Тогда //⚡ Ключ = СокрЛП(Пара[0]); //✏ Значение = СокрЛП(Пара[1]); //✏ // URL-декодировка частых случаев Значение = СтрЗаменить(Значение, "%20", " "); //✏ Значение = СтрЗаменить(Значение, "%2B", "+"); //✏ Значение = СтрЗаменить(Значение, "%26", "&"); //✏ Результат.Вставить(Ключ, Значение); //✏ КонецЕсли; КонецЦикла; Возврат Результат; //↩ КонецФункции #Region Public_Selection_Methods // // Создает структуру из другой структуры, выбирая только указанные ключи. ✦ // Исходная структура ➤ // Строка нужных ключей через запятую ➤ // Structure — новая структура с выбранными полями ⬅ // // // // user = A1sDS.Of("name", "John", "age", 30, "password", "secret"); // // public = A1sDS.OfPick(user, "name,age"); // // -> {name: "John", age: 30} // // Функция OfPick(SourceStruct, KeysString) Экспорт //⚙ ib = "Выборка ключей из структуры"; //✍ НужныеКлючи = СтрРазделить(KeysString, ","); //✏ Результат = Новый Структура(); //✏ Для Каждого КлючСтрока Из НужныеКлючи Цикл //⟳ Ключ = СокрЛП(КлючСтрока); //✏ Если ЗначениеЗаполнено(Ключ) И SourceStruct.Свойство(Ключ) Тогда //⚡ Результат.Вставить(Ключ, SourceStruct[Ключ]); //✏ КонецЕсли; КонецЦикла; Возврат Результат; //↩ КонецФункции // // Создает структуру из другой структуры, исключая указанные ключи. ✦ // Исходная структура ➤ // Строка исключаемых ключей через запятую ➤ // Structure — новая структура без исключенных полей ⬅ // // // // user = A1sDS.Of("name", "John", "age", 30, "password", "secret"); // // safe = A1sDS.OfOmit(user, "password"); // // -> {name: "John", age: 30} // // Функция OfOmit(SourceStruct, ExcludeKeysString) Экспорт //⚙ ib = "Исключение ключей из структуры"; //✍ ИсключаемыеКлючи = СтрРазделить(ExcludeKeysString, ","); //✏ СоответствиеИсключений = Новый Соответствие(); //✏ // Создаем соответствие для быстрого поиска исключений Для Каждого КлючСтрока Из ИсключаемыеКлючи Цикл //⟳ Ключ = СокрЛП(КлючСтрока); //✏ Если ЗначениеЗаполнено(Ключ) Тогда //⚡ СоответствиеИсключений.Вставить(Ключ, Истина); //✏ КонецЕсли; КонецЦикла; Результат = Новый Структура(); //✏ // Копируем все ключи, кроме исключенных Для Каждого Пара Из SourceStruct Цикл //⟳ Если СоответствиеИсключений[Пара.Ключ] = Неопределено Тогда //⚡ Результат.Вставить(Пара.Ключ, Пара.Значение); //✏ КонецЕсли; КонецЦикла; Возврат Результат; //↩ КонецФункции #КонецОбласти #Region Public_Modification_Methods // // Создает структуру, объединив данные с заданными значениями по умолчанию. ✦ // Исходная структура ➤ // Структура значений по умолчанию ➤ // Structure — новая структура с примененными значениями по умолчанию ⬅ // // // // config = A1sDS.Of("host", "localhost"); // // defaults = A1sDS.Of("host", "127.0.0.1", "port", 8080, "timeout", 30); // // result = A1sDS.OfDefaults(config, defaults); // // -> {host: "localhost", port: 8080, timeout: 30} // // Функция OfDefaults(SourceStruct, DefaultsStruct) Экспорт //⚙ ib = "Применение значений по умолчанию"; //✍ Результат = Новый Структура(); //✏ // Сначала заполняем значениями по умолчанию Для Каждого Пара Из DefaultsStruct Цикл //⟳ Результат.Вставить(Пара.Ключ, Пара.Значение); //✏ КонецЦикла; // Затем перезаписываем переданными значениями Для Каждого Пара Из SourceStruct Цикл //⟳ Результат.Вставить(Пара.Ключ, Пара.Значение); //✏ КонецЦикла; Возврат Результат; //↩ КонецФункции // // Создает новую структуру с переименованными ключами. ✦ // Исходная структура ➤ // Карта переименования: {старое_имя: "новое_имя"} ➤ // Structure — структура с переименованными ключами ⬅ // // // // user = A1sDS.Of("first_name", "John", "last_name", "Doe"); // // map = A1sDS.Of("first_name", "имя", "last_name", "фамилия"); // // result = A1sDS.OfRename(user, map); // // -> {имя: "John", фамилия: "Doe"} // // Функция OfRename(SourceStruct, RenameMap) Экспорт //⚙ ib = "Переименование ключей структуры"; //✍ Результат = Новый Структура(); //✏ Для Каждого Пара Из SourceStruct Цикл //⟳ НовоеИмя = Пара.Ключ; //✏ // Проверяем, есть ли переименование для этого ключа Если RenameMap.Свойство(Пара.Ключ) Тогда //⚡ НовоеИмя = RenameMap[Пара.Ключ]; //✏ КонецЕсли; Результат.Вставить(НовоеИмя, Пара.Значение); //✏ КонецЦикла; Возврат Результат; //↩ КонецФункции // // Добавляет свойство в структуру по условию. ✦ // Структура для изменения ➤ // Имя свойства ➤ // Значение при истинном условии ➤ // Условие добавления свойства ➤ // Значение при ложном условии ➤ // Structure — переданная структура с добавленным свойством или без изменений ⬅ // // // // struct = A1sDS.Of("name", "John"); // // A1sDS.AddIf(struct, "age", 30, Истина, 0); // // -> {name: "John", age: 30} // // Функция AddIf(Структура, Ключ, ЗначениеЕслиИстина, Условие = Истина, ЗначениеЕслиЛожь = Неопределено) Экспорт //⚙ ib = "Добавление свойства по условию"; //✍ Если Условие Тогда //⚡ Структура.Вставить(Ключ, ЗначениеЕслиИстина); //✏ ИначеЕсли ЗначениеЕслиЛожь <> Неопределено Тогда //⚡ Структура.Вставить(Ключ, ЗначениеЕслиЛожь); //✏ КонецЕсли; Возврат Структура; //↩ КонецФункции #КонецОбласти #Region Public_Combine_Methods // // Объединяет до 8 структур, значения последующих перезаписывают предыдущие. ✦ // Первая структура ➤ // Вторая структура ➤ // Третья структура ➤ // Четвертая структура ➤ // Пятая структура ➤ // Шестая структура ➤ // Седьмая структура ➤ // Восьмая структура ➤ // Structure — объединенная структура ⬅ // // // // s1 = A1sDS.Of("a", 1, "b", 2); // // s2 = A1sDS.Of("b", 3, "c", 4); // // A1sDS.Concatenate(s1, s2) -> {a: 1, b: 3, c: 4} // // Функция Concatenate(Структура1, Структура2 = Неопределено, Структура3 = Неопределено, Структура4 = Неопределено, Структура5 = Неопределено, Структура6 = Неопределено, Структура7 = Неопределено, Структура8 = Неопределено) Экспорт //⚙ ib = "Объединение структур"; //✍ НоваяСтруктура = Новый Структура(); //✏ // Создаем массив всех переданных структур для итерации СтруктурыДляОбъединения = Новый Массив(); //✏ Если Структура1 <> Неопределено И ТипЗнч(Структура1) = Тип("Структура") Тогда СтруктурыДляОбъединения.Добавить(Структура1); КонецЕсли; //⚡ Если Структура2 <> Неопределено И ТипЗнч(Структура2) = Тип("Структура") Тогда СтруктурыДляОбъединения.Добавить(Структура2); КонецЕсли; //⚡ Если Структура3 <> Неопределено И ТипЗнч(Структура3) = Тип("Структура") Тогда СтруктурыДляОбъединения.Добавить(Структура3); КонецЕсли; //⚡ Если Структура4 <> Неопределено И ТипЗнч(Структура4) = Тип("Структура") Тогда СтруктурыДляОбъединения.Добавить(Структура4); КонецЕсли; //⚡ Если Структура5 <> Неопределено И ТипЗнч(Структура5) = Тип("Структура") Тогда СтруктурыДляОбъединения.Добавить(Структура5); КонецЕсли; //⚡ Если Структура6 <> Неопределено И ТипЗнч(Структура6) = Тип("Структура") Тогда СтруктурыДляОбъединения.Добавить(Структура6); КонецЕсли; //⚡ Если Структура7 <> Неопределено И ТипЗнч(Структура7) = Тип("Структура") Тогда СтруктурыДляОбъединения.Добавить(Структура7); КонецЕсли; //⚡ Если Структура8 <> Неопределено И ТипЗнч(Структура8) = Тип("Структура") Тогда СтруктурыДляОбъединения.Добавить(Структура8); КонецЕсли; //⚡ // Объединяем все структуры Для Каждого ТекущаяСтруктура Из СтруктурыДляОбъединения Цикл //⟳ Для Каждого Пара Из ТекущаяСтруктура Цикл //⟳ НоваяСтруктура.Вставить(Пара.Ключ, Пара.Значение); //✏ КонецЦикла; КонецЦикла; Возврат НоваяСтруктура; //↩ КонецФункции // // Объединение множеств ключей до 8 структур - возвращает структуру со всеми уникальными ключами. ✦ // Первая структура ➤ // Вторая структура ➤ // Третья структура ➤ // Четвертая структура ➤ // Пятая структура ➤ // Шестая структура ➤ // Седьмая структура ➤ // Восьмая структура ➤ // Structure — объединенная структура со всеми уникальными ключами ⬅ // // // // s1 = A1sDS.Of("a", 1); s2 = A1sDS.Of("b", 2); // // A1sDS.Union(s1, s2) -> {a: 1, b: 2} // // Функция Union(Структура1, Структура2 = Неопределено, Структура3 = Неопределено, Структура4 = Неопределено, Структура5 = Неопределено, Структура6 = Неопределено, Структура7 = Неопределено, Структура8 = Неопределено) Экспорт //⚙ ib = "Объединение множеств ключей"; //✍ Возврат Concatenate(Структура1, Структура2, Структура3, Структура4, Структура5, Структура6, Структура7, Структура8); //↩ КонецФункции // // Возвращает структуру с ключами, которые есть во всех переданных структурах (пересечение до 8 структур). ✦ // Первая структура ➤ // Вторая структура ➤ // Третья структура ➤ // Четвертая структура ➤ // Пятая структура ➤ // Шестая структура ➤ // Седьмая структура ➤ // Восьмая структура ➤ // Structure — пересечение структур ⬅ // // // // s1 = A1sDS.Of("a", 1, "b", 2); s2 = A1sDS.Of("b", 3, "c", 4); // // A1sDS.Intersection(s1, s2) -> {b: 3} // // Функция Intersection(Структура1, Структура2 = Неопределено, Структура3 = Неопределено, Структура4 = Неопределено, Структура5 = Неопределено, Структура6 = Неопределено, Структура7 = Неопределено, Структура8 = Неопределено) Экспорт //⚙ ib = "Пересечение структур"; //✍ // Создаем массив всех переданных структур ВсеСтруктуры = Новый Массив(); //✏ Если Структура1 <> Неопределено И ТипЗнч(Структура1) = Тип("Структура") Тогда ВсеСтруктуры.Добавить(Структура1); КонецЕсли; //⚡ Если Структура2 <> Неопределено И ТипЗнч(Структура2) = Тип("Структура") Тогда ВсеСтруктуры.Добавить(Структура2); КонецЕсли; //⚡ Если Структура3 <> Неопределено И ТипЗнч(Структура3) = Тип("Структура") Тогда ВсеСтруктуры.Добавить(Структура3); КонецЕсли; //⚡ Если Структура4 <> Неопределено И ТипЗнч(Структура4) = Тип("Структура") Тогда ВсеСтруктуры.Добавить(Структура4); КонецЕсли; //⚡ Если Структура5 <> Неопределено И ТипЗнч(Структура5) = Тип("Структура") Тогда ВсеСтруктуры.Добавить(Структура5); КонецЕсли; //⚡ Если Структура6 <> Неопределено И ТипЗнч(Структура6) = Тип("Структура") Тогда ВсеСтруктуры.Добавить(Структура6); КонецЕсли; //⚡ Если Структура7 <> Неопределено И ТипЗнч(Структура7) = Тип("Структура") Тогда ВсеСтруктуры.Добавить(Структура7); КонецЕсли; //⚡ Если Структура8 <> Неопределено И ТипЗнч(Структура8) = Тип("Структура") Тогда ВсеСтруктуры.Добавить(Структура8); КонецЕсли; //⚡ Если ВсеСтруктуры.Количество() = 0 Тогда //⚡ Возврат Новый Структура(); //↩ КонецЕсли; Если ВсеСтруктуры.Количество() = 1 Тогда //⚡ // Создаем копию первой структуры Результат = Новый Структура(); //✏ Для Каждого Пара Из ВсеСтруктуры[0] Цикл //⟳ Результат.Вставить(Пара.Ключ, Пара.Значение); //✏ КонецЦикла; Возврат Результат; //↩ КонецЕсли; // Начинаем с ключей первой структуры Результат = Новый Структура(); //✏ ПерваяСтруктура = ВсеСтруктуры[0]; //✏ // Проверяем каждый ключ первой структуры Для Каждого Пара Из ПерваяСтруктура Цикл //⟳ КлючПрисутствуетВоВсех = Истина; //✏ // Проверяем присутствие ключа в остальных структурах Для Индекс = 1 По ВсеСтруктуры.Количество() - 1 Цикл //⟳ Если НЕ ВсеСтруктуры[Индекс].Свойство(Пара.Ключ) Тогда //⚡ КлючПрисутствуетВоВсех = Ложь; //✏ Прервать; //✖ КонецЕсли; КонецЦикла; // Если ключ присутствует во всех структурах, берем значение из последней структуры Если КлючПрисутствуетВоВсех Тогда //⚡ ЗначениеДляВставки = Пара.Значение; //✏ // Берем значение из последней структуры, которая содержит этот ключ Индекс = ВсеСтруктуры.Количество() - 1; //✏ Пока Индекс >= 0 Цикл //⟳ Если ВсеСтруктуры[Индекс].Свойство(Пара.Ключ) Тогда //⚡ ЗначениеДляВставки = ВсеСтруктуры[Индекс][Пара.Ключ]; //✏ Прервать; //✖ КонецЕсли; Индекс = Индекс - 1; //✏ КонецЦикла; Результат.Вставить(Пара.Ключ, ЗначениеДляВставки); //✏ КонецЕсли; КонецЦикла; Возврат Результат; //↩ КонецФункции // // Возвращает структуру с ключами из первой структуры, которых нет в остальных структурах (разность до 8 структур). ✦ // Первая структура ➤ // Вторая структура ➤ // Третья структура ➤ // Четвертая структура ➤ // Пятая структура ➤ // Шестая структура ➤ // Седьмая структура ➤ // Восьмая структура ➤ // Structure — разность структур ⬅ // // // // s1 = A1sDS.Of("a", 1, "b", 2); s2 = A1sDS.Of("b", 3, "c", 4); // // A1sDS.Difference(s1, s2) -> {a: 1} // // Функция Difference(Структура1, Структура2 = Неопределено, Структура3 = Неопределено, Структура4 = Неопределено, Структура5 = Неопределено, Структура6 = Неопределено, Структура7 = Неопределено, Структура8 = Неопределено) Экспорт //⚙ ib = "Разность структур"; //✍ Если Структура1 = Неопределено Или ТипЗнч(Структура1) <> Тип("Структура") Тогда //⚡ Возврат Новый Структура(); //↩ КонецЕсли; // Создаем массив структур для исключения СтруктурыИсключения = Новый Массив(); //✏ Если Структура2 <> Неопределено И ТипЗнч(Структура2) = Тип("Структура") Тогда СтруктурыИсключения.Добавить(Структура2); КонецЕсли; //⚡ Если Структура3 <> Неопределено И ТипЗнч(Структура3) = Тип("Структура") Тогда СтруктурыИсключения.Добавить(Структура3); КонецЕсли; //⚡ Если Структура4 <> Неопределено И ТипЗнч(Структура4) = Тип("Структура") Тогда СтруктурыИсключения.Добавить(Структура4); КонецЕсли; //⚡ Если Структура5 <> Неопределено И ТипЗнч(Структура5) = Тип("Структура") Тогда СтруктурыИсключения.Добавить(Структура5); КонецЕсли; //⚡ Если Структура6 <> Неопределено И ТипЗнч(Структура6) = Тип("Структура") Тогда СтруктурыИсключения.Добавить(Структура6); КонецЕсли; //⚡ Если Структура7 <> Неопределено И ТипЗнч(Структура7) = Тип("Структура") Тогда СтруктурыИсключения.Добавить(Структура7); КонецЕсли; //⚡ Если Структура8 <> Неопределено И ТипЗнч(Структура8) = Тип("Структура") Тогда СтруктурыИсключения.Добавить(Структура8); КонецЕсли; //⚡ // Создаем соответствие всех ключей для исключения КлючиИсключения = Новый Соответствие(); //✏ Для Каждого СтруктураИсключения Из СтруктурыИсключения Цикл //⟳ Для Каждого Пара Из СтруктураИсключения Цикл //⟳ КлючиИсключения.Вставить(Пара.Ключ, Истина); //✏ КонецЦикла; КонецЦикла; // Формируем результат Результат = Новый Структура(); //✏ Для Каждого Пара Из Структура1 Цикл //⟳ Если КлючиИсключения[Пара.Ключ] = Неопределено Тогда //⚡ Результат.Вставить(Пара.Ключ, Пара.Значение); //✏ КонецЕсли; КонецЦикла; Возврат Результат; //↩ КонецФункции #КонецОбласти #Region Public_Utility_Methods // // Создает фиксированную структуру из структуры или массива пар. ✦ // Структура или массив пар ➤ // FixedStructure — новая фиксированная структура ⬅ // // // // struct = A1sDS.Of("x", 10, "y", 20); // // A1sDS.ToFixed(struct) -> ФиксированнаяСтруктура{x: 10, y: 20} // // Функция ToFixed(Источник) Экспорт //⚙ ib = "Создание фиксированной структуры"; //✍ Если ТипЗнч(Источник) = Тип("Структура") Тогда //⚡ Возврат Новый ФиксированнаяСтруктура(Источник); //↩ ИначеЕсли ТипЗнч(Источник) = Тип("Массив") Тогда //⚡ Возврат Новый ФиксированнаяСтруктура(OfPairs(Источник)); //↩ Иначе Возврат Новый ФиксированнаяСтруктура(); //↩ КонецЕсли; КонецФункции // // Преобразует структуру в массив пар. ✦ // Исходная структура ➤ // Array — массив пар-структур с полями Ключ и Значение ⬅ // // // // struct = A1sDS.Of("x", 10, "y", 20); // // A1sDS.ToPairs(struct) -> [{Ключ: "x", Значение: 10}, {Ключ: "y", Значение: 20}] // // Функция ToPairs(Структура) Экспорт //⚙ ib = "Преобразование структуры в массив пар"; //✍ МассивПар = Новый Массив(); //✏ Для Каждого Пара Из Структура Цикл //⟳ МассивПар.Добавить(Pair(Пара.Ключ, Пара.Значение)); //▶️ КонецЦикла; Возврат МассивПар; //↩ КонецФункции // // Глубокое копирование структуры (рекурсивно копирует вложенные структуры). ✦ // Структура для копирования ➤ // Structure — глубокая копия структуры ⬅ // // // // nested = A1sDS.Of("inner", A1sDS.Of("value", 42)); // // copy = A1sDS.DeepCopy(nested); // // Функция DeepCopy(ИсходнаяСтруктура) Экспорт //⚙ ib = "Глубокое копирование структуры"; //✍ НоваяСтруктура = Новый Структура(); //✏ Для Каждого Пара Из ИсходнаяСтруктура Цикл //⟳ Значение = Пара.Значение; //✏ Если ТипЗнч(Значение) = Тип("Структура") Тогда //⚡ Значение = DeepCopy(Значение); //▶️ КонецЕсли; НоваяСтруктура.Вставить(Пара.Ключ, Значение); //✏ КонецЦикла; Возврат НоваяСтруктура; //↩ КонецФункции // // Проверяет наличие ключа в структуре. ✦ // Структура для проверки ➤ // Проверяемый ключ ➤ // Boolean — истина, если ключ существует ⬅ // // // // struct = A1sDS.Of("name", "John"); // // A1sDS.HasKey(struct, "name") -> Истина // // A1sDS.HasKey(struct, "age") -> Ложь // // Функция HasKey(Структура, Ключ) Экспорт //⚙ ib = "Проверка наличия ключа"; //✍ Возврат Структура.Свойство(Ключ) <> Неопределено; //↩ КонецФункции // // Возвращает массив ключей структуры. ✦ // Исходная структура ➤ // Array — массив строк-ключей ⬅ // // // // struct = A1sDS.Of("name", "John", "age", 30); // // A1sDS.GetKeys(struct) -> ["name", "age"] // // Функция GetKeys(Структура) Экспорт //⚙ ib = "Получение массива ключей"; //✍ Ключи = Новый Массив(); //✏ Для Каждого Пара Из Структура Цикл //⟳ Ключи.Добавить(Пара.Ключ); //✏ КонецЦикла; Возврат Ключи; //↩ КонецФункции // // Возвращает массив значений структуры. ✦ // Исходная структура ➤ // Array — массив значений ⬅ // // // // struct = A1sDS.Of("name", "John", "age", 30); // // A1sDS.GetValues(struct) -> ["John", 30] // // Функция GetValues(Структура) Экспорт //⚙ ib = "Получение массива значений"; //✍ Значения = Новый Массив(); //✏ Для Каждого Пара Из Структура Цикл //⟳ Значения.Добавить(Пара.Значение); //✏ КонецЦикла; Возврат Значения; //↩ КонецФункции // // Преобразует структуру в многострочную строку для отладки. ✦ // Структура для отображения ➤ // String — многострочное представление структуры ⬅ // // // // struct = A1sDS.Of("name", "John", "age", 30); // // A1sDS.ToString(struct) -> "name = John\nage = 30\n" // // Функция ToString(Структура) Экспорт //⚙ ib = "Преобразование структуры в строку"; //✍ Результат = ""; //✏ Для Каждого Пара Из Структура Цикл //⟳ Результат = Результат + Пара.Ключ + " = " + Строка(Пара.Значение) + Символы.ПС; //✏ КонецЦикла; Возврат Результат; //↩ КонецФункции // // Проверяет, пуста ли структура (нет свойств). ✦ // Структура для проверки ➤ // Boolean — истина, если структура пустая ⬅ // // // // A1sDS.IsEmpty(Новый Структура()) -> Истина // // A1sDS.IsEmpty(A1sDS.Of("x", 1)) -> Ложь // // Функция IsEmpty(Структура) Экспорт //⚙ ib = "Проверка пустоты структуры"; //✍ Для Каждого Пара Из Структура Цикл //⟳ Возврат Ложь; //↩ КонецЦикла; Возврат Истина; //↩ КонецФункции #КонецОбласти // ================================================================= // A1sDS — Helpers for 1C Structure (get_or_insert, path) // ================================================================= #Область PublicAPI #Region A1sDS_GetOrInsert /// /// Возвращает значение по ключу из Структуры; если ключа нет — вставляет умолчание и возвращает его. /// Целевая структура (ДОЛЖНА быть создана вызывающим кодом). /// Имя ключа. /// Значение по умолчанию (вставляется как есть). /// Variant — существующее значение или вставленное умолчание. /// /// /// Prefs = Новый Структура; /// Dark = A1sDS.GetOrInsert(Prefs, "useDarkmode", Истина); // запишет Истина один раз /// /// Функция GetOrInsert(Struct, Key, DefaultValue) Экспорт Если ТипЗнч(Struct) <> Тип("Структура") Тогда ВызватьИсключение "A1sDS.GetOrInsert: параметр Struct должен быть типа Структура"; КонецЕсли; Если Struct.Свойство(Key) Тогда Возврат Struct[Key]; КонецЕсли; Struct.Вставить(Key, DefaultValue); Возврат DefaultValue; КонецФункции #EndRegion #Region A1sDS_GetOrInsertEval /// /// Ленивая версия: если ключ отсутствует — вычисляет выражение строкой, вставляет и возвращает. /// Целевая структура (ДОЛЖНА быть создана вызывающим кодом). /// Имя ключа. /// BSL-выражение, которое вернёт значение (выполняется ТОЛЬКО если ключ отсутствует). /// Variant — существующее значение или вычисленное и вставленное. /// /// /// Cache = Новый Структура; /// // Компилируем дорогую регулярку лишь однажды: /// Rx = A1sDS.GetOrInsertEval(Cache, "rxINN", "Новый РегулярноеВыражение(""^\d{10}(\d{2})?$"")"); /// /// Функция GetOrInsertEval(Struct, Key, ValueExpr) Экспорт Если ТипЗнч(Struct) <> Тип("Структура") Тогда ВызватьИсключение "A1sDS.GetOrInsertEval: параметр Struct должен быть типа Структура"; КонецЕсли; Если Struct.Свойство(Key) Тогда Возврат Struct[Key]; КонецЕсли; Значение = Вычислить(ValueExpr); Struct.Вставить(Key, Значение); Возврат Значение; КонецФункции #EndRegion #Region A1sDS_GetOrInsertPath /// /// Вставляет умолчание по «пути ключей» в Структуре (создаёт промежуточные узлы) и возвращает конечное значение. /// Целевая структура (ДОЛЖНА быть создана вызывающим кодом). /// Путь вида "ui.theme.dark" (разделитель по умолчанию "."). /// Умолчание для конечного ключа. /// Разделитель пути. /// Variant — существующее конечное значение или вставленное умолчание. /// /// Сегменты пути /// Количество сегментов /// Текущий узел /// Индекс цикла /// Текущий ключ /// /// /// /// Prefs = Новый Структура; /// // Создаст: ui = { theme = { dark = Истина } } /// A1sDS.GetOrInsertPath(Prefs, "ui.theme.dark", Истина); /// /// Функция GetOrInsertPath(Struct, Path, DefaultValue, Sep = ".") Экспорт Если ТипЗнч(Struct) <> Тип("Структура") Тогда ВызватьИсключение "A1sDS.GetOrInsertPath: параметр Struct должен быть типа Структура"; КонецЕсли; parts = СтрРазделить(Path, Sep, Ложь); count = parts.Количество(); Если count = 0 Тогда Возврат DefaultValue; КонецЕсли; node = Struct; Если count > 1 Тогда Для i = 0 По count - 2 Цикл k = СокрЛП(parts[i]); Если НЕ node.Свойство(k) Тогда node.Вставить(k, Новый Структура); ИначеЕсли ТипЗнч(node[k]) <> Тип("Структура") Тогда // Если по пути уже лежит не-структура — аккуратно заменяем на узел-структуру node[k] = Новый Структура; КонецЕсли; node = node[k]; КонецЦикла; КонецЕсли; // Последний сегмент k = СокрЛП(parts[count - 1]); Если node.Свойство(k) Тогда Возврат node[k]; КонецЕсли; node.Вставить(k, DefaultValue); Возврат DefaultValue; КонецФункции #EndRegion #КонецОбласти // ================================================================= // Примеры использования (закомментированы — раскомментируйте для прогона) // ================================================================= #Region examples_A1sDS // Процедура A1sDS_Demo() Экспорт // Параметры = Новый Структура; // // // 1) Базовый get_or_insert — дефолт пишется один раз // Тёмная1 = A1sDS.GetOrInsert(Параметры, "useDarkmode", Истина); // Тёмная2 = A1sDS.GetOrInsert(Параметры, "useDarkmode", Ложь); // НЕ перезапишет // // A1sS.Print("useDarkmode: " + Строка(Параметры.useDarkmode)); // Истина // // // 2) Ленивая версия — «дорогая» штука компилируется один раз // Перем Счётчик; Счётчик = 0; // // Функция _Expensive() Экспорт // // Счётчик = Счётчик + 1; Пауза(0.2); // // Возврат Новый РегулярноеВыражение("^\d{10}(\d{2})?$"); // // КонецФункции // Rx1 = A1sDS.GetOrInsertEval(Параметры, "rxINN", "_Expensive()"); // Rx2 = A1sDS.GetOrInsertEval(Параметры, "rxINN", "_Expensive()"); // // A1sS.Print("rxINN тот же объект: " + Строка(Rx1 = Rx2)); // Истина // // A1sS.Print("Вызовов _Expensive(): " + Строка(Счётчик)); // 1 // // // 3) Путь ключей — создаст промежуточные узлы // Настройки = Новый Структура; // A1sDS.GetOrInsertPath(Настройки, "ui.theme.dark", Истина); // // A1sS.Print("ui.theme.dark: " + Строка(Настройки.ui.theme.dark)); // Истина // // // Повтор по тому же пути — не перезапишет // A1sDS.GetOrInsertPath(Настройки, "ui.theme.dark", Ложь); // // A1sS.Print("ui.theme.dark (повтор): " + Строка(Настройки.ui.theme.dark)); // Истина // КонецПроцедуры #EndRegion #Region Tests_And_Examples // // Самотест модуля A1sDS с примерами использования. ✦ // Boolean — все тесты пройдены успешно ⬅ // // Функция SelfTest() Экспорт //⚙ ib = "Самотест A1sDS"; //✍ TestsPassed = 0; //✏ TestsTotal = 0; //✏ Сообщить("=== A1sDS.SelfTest() START ==="); // Тест 1: Of - создание структуры из пар ключ-значение TestsTotal = TestsTotal + 1; //✏ TestStruct1 = Of("name", "John", "age", 30, "city", "NYC"); //✏ Если TestStruct1.Свойство("name") И TestStruct1.name = "John" И TestStruct1.age = 30 И TestStruct1.city = "NYC" Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 1 (Of создание): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 1 (Of создание): ПРОВАЛЕН"); КонецЕсли; // Тест 2: OfKeysAndValues - создание из ключей и значений TestsTotal = TestsTotal + 1; //✏ TestKeys = "x,y,z"; //✏ TestValues = Новый Массив(); //✏ TestValues.Добавить(10); //✏ TestValues.Добавить(20); //✏ TestValues.Добавить(30); //✏ TestStruct2 = OfKeysAndValues(TestKeys, TestValues); //✏ Если TestStruct2.x = 10 И TestStruct2.y = 20 И TestStruct2.z = 30 Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 2 (OfKeysAndValues): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 2 (OfKeysAndValues): ПРОВАЛЕН"); КонецЕсли; // Тест 3: OfPick - выборка ключей TestsTotal = TestsTotal + 1; //✏ TestUser = Of("name", "John", "age", 30, "password", "secret", "email", "john@test.com"); //✏ TestPublic = OfPick(TestUser, "name,age,email"); //✏ Если TestPublic.Свойство("name") И TestPublic.Свойство("age") И TestPublic.Свойство("email") И НЕ TestPublic.Свойство("password") Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 3 (OfPick): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 3 (OfPick): ПРОВАЛЕН"); КонецЕсли; // Тест 4: OfOmit - исключение ключей TestsTotal = TestsTotal + 1; //✏ TestSafe = OfOmit(TestUser, "password"); //✏ Если TestSafe.Свойство("name") И TestSafe.Свойство("age") И НЕ TestSafe.Свойство("password") Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 4 (OfOmit): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 4 (OfOmit): ПРОВАЛЕН"); КонецЕсли; // Тест 5: OfDefaults - значения по умолчанию TestsTotal = TestsTotal + 1; //✏ TestConfig = Of("host", "localhost"); //✏ TestDefaults = Of("host", "127.0.0.1", "port", 8080, "timeout", 30); //✏ TestResult = OfDefaults(TestConfig, TestDefaults); //✏ Если TestResult.host = "localhost" И TestResult.port = 8080 И TestResult.timeout = 30 Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 5 (OfDefaults): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 5 (OfDefaults): ПРОВАЛЕН"); КонецЕсли; // Тест 6: Concatenate - объединение структур TestsTotal = TestsTotal + 1; //✏ TestS1 = Of("a", 1, "b", 2); //✏ TestS2 = Of("b", 3, "c", 4); //✏ TestMerged = Concatenate(TestS1, TestS2); //✏ Если TestMerged.a = 1 И TestMerged.b = 3 И TestMerged.c = 4 Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 6 (Concatenate): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 6 (Concatenate): ПРОВАЛЕН"); КонецЕсли; // Тест 7: HasKey - проверка наличия ключа TestsTotal = TestsTotal + 1; //✏ TestStruct7 = Of("exists", "yes"); //✏ Если HasKey(TestStruct7, "exists") И НЕ HasKey(TestStruct7, "missing") Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 7 (HasKey): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 7 (HasKey): ПРОВАЛЕН"); КонецЕсли; // Тест 8: GetKeys - получение ключей TestsTotal = TestsTotal + 1; //✏ TestStruct8 = Of("first", 1, "second", 2); //✏ TestKeys8 = GetKeys(TestStruct8); //✏ Если TestKeys8.Количество() = 2 И (TestKeys8.Найти("first") <> Неопределено) И (TestKeys8.Найти("second") <> Неопределено) Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 8 (GetKeys): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 8 (GetKeys): ПРОВАЛЕН"); КонецЕсли; // Тест 9: IsEmpty - проверка пустоты TestsTotal = TestsTotal + 1; //✏ EmptyStruct = Новый Структура(); //✏ NonEmptyStruct = Of("test", "value"); //✏ Если IsEmpty(EmptyStruct) И НЕ IsEmpty(NonEmptyStruct) Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 9 (IsEmpty): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 9 (IsEmpty): ПРОВАЛЕН"); КонецЕсли; // Тест 10: OfQueryString - разбор QueryString TestsTotal = TestsTotal + 1; //✏ TestQS = OfQueryString("name=John&age=30&city=New%20York"); //✏ Если TestQS.name = "John" И TestQS.age = "30" И TestQS.city = "New York" Тогда //⚡ TestsPassed = TestsPassed + 1; //✏ Сообщить("✓ Тест 10 (OfQueryString): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 10 (OfQueryString): ПРОВАЛЕН"); КонецЕсли; // Итоги тестирования Если TestsPassed = TestsTotal Тогда //⚡ Сообщить("=== A1sDS.SelfTest() SUCCESS: " + Строка(TestsPassed) + "/" + Строка(TestsTotal) + " ==="); Возврат Истина; //↩ Иначе Сообщить("=== A1sDS.SelfTest() FAILED: " + Строка(TestsPassed) + "/" + Строка(TestsTotal) + " ==="); Возврат Ложь; //↩ КонецЕсли; КонецФункции // // Расширенные примеры использования функций модуля A1sDS. ✦ // Процедура ExamplesAdvanced() Экспорт //⚙ ib = "Примеры A1sDS"; //✍ Сообщить("=== Примеры использования A1sDS ==="); // Пример 1: API Response Processing APIResponse = Of("user_id", 123, "user_name", "john_doe", "user_email", "john@example.com", "internal_token", "secret123"); //✏ PublicData = OfPick(APIResponse, "user_id,user_name,user_email"); //▶️ Сообщить("API публичные данные: " + ToString(PublicData)); // Пример 2: Configuration with Defaults UserConfig = Of("database_host", "prod-server"); //✏ DefaultConfig = Of("database_host", "localhost", "database_port", 5432, "timeout", 30, "pool_size", 10); //✏ FinalConfig = OfDefaults(UserConfig, DefaultConfig); //▶️ Сообщить("Итоговая конфигурация:"); Сообщить(ToString(FinalConfig)); // Пример 3: Data Transformation Pipeline RawData = Of("firstName", "John", "lastName", "Doe", "emailAddress", "john@example.com"); //✏ RenameMap = Of("firstName", "имя", "lastName", "фамилия", "emailAddress", "email"); //✏ TransformedData = OfRename(RawData, RenameMap); //▶️ Сообщить("Трансформированные данные:"); Сообщить(ToString(TransformedData)); // Пример 4: Query String to Structure URLParams = "action=search&query=product&category=electronics&page=2&limit=20"; //✏ ParsedParams = OfQueryString(URLParams); //▶️ Сообщить("Разобранные URL параметры:"); Сообщить(ToString(ParsedParams)); // Пример 5: Complex Structure Operations UserProfile = Of("id", 1, "name", "John", "permissions", "read,write", "created", "2024-01-01"); //✏ UserSettings = Of("theme", "dark", "language", "ru", "notifications", Истина); //✏ UserSession = Of("token", "abc123", "expires", "2024-12-31", "ip", "192.168.1.1"); //✏ // Объединяем все данные пользователя FullUserData = Concatenate(UserProfile, UserSettings, UserSession); //▶️ // Создаем безопасную версию для логов (без токенов) SafeUserData = OfOmit(FullUserData, "token,ip"); //▶️ Сообщить("Безопасные данные пользователя для логов:"); Сообщить(ToString(SafeUserData)); Сообщить("=== Примеры завершены ==="); КонецПроцедуры #КонецОбласти // // Возвращает версию модуля A1sDS. ✦ // String — версия модуля (например, "1.0.0") ⬅ // // Функция GetVersion() Экспорт //⚙ ib = "Получение версии модуля"; //✍ Возврат "1.0.0"; //↩ КонецФункции //////////////////////////////////////////////////////////////////////////////// // МОДУЛЬ ЗАВЕРШЕН - A1sDS v1.0.0 // Готов к производственному использованию! // // Основные возможности: // - Создание структур: Of(), OfKeysAndValues(), OfString(), OfQueryString() // - Фильтрация данных: OfPick(), OfOmit() // - Конфигурирование: OfDefaults(), OfRename() // - Объединение: Concatenate(), Union() // - Утилиты: HasKey(), GetKeys(), GetValues(), IsEmpty(), ToString() // - Преобразования: ToPairs(), ToFixed(), DeepCopy() // // Полностью совместим со стандартами A1sCode: // ✅ XML-документация для всех функций // ✅ SyntaxMarks для всех конструкций // ✅ Комплексное тестирование // ✅ Продвинутые примеры использования // // Сайт: https://a1scode.ru // Лицензия: MIT ////////////////////////////////////////////////////////////////////////////////