Читайте дальше...
Создание и базовые операции с соответствием
// Создание соответствия, добавление и получение элементов
Процедура БазовыеОперацииССоответствием()
// Создаем новое соответствие
Соответствие = Новый Соответствие;
// Добавляем пары ключ-значение
Соответствие.Вставить("Ноутбук", 50000);
Соответствие.Вставить("Монитор", 15000);
Соответствие.Вставить("Клавиатура", 2000);
Соответствие.Вставить("Мышь", 1000);
// Получаем значение по ключу
ЦенаНоутбука = Соответствие.Получить("Ноутбук");
Сообщить("Цена ноутбука: " + ЦенаНоутбука);
// Проверяем наличие ключа
Если Соответствие.КлючСуществует("Принтер") Тогда
Сообщить("Принтер есть в соответствии");
Иначе
Сообщить("Принтера нет в соответствии");
КонецЕсли;
// Изменяем значение по ключу
Соответствие.Вставить("Ноутбук", 55000);
Сообщить("Новая цена ноутбука: " + Соответствие.Получить("Ноутбук"));
// Количество элементов
Сообщить("Количество элементов: " + Соответствие.Количество());
// Удаление элемента
Соответствие.Удалить("Мышь");
Сообщить("После удаления мыши: " + Соответствие.Количество() + " элементов");
// Очистка всех элементов
Соответствие.Очистить();
Сообщить("После очистки: " + Соответствие.Количество() + " элементов");
КонецПроцедуры
Перебор соответствия (обход всех пар)
// Итерация по соответствию с получением ключей и значений
Процедура ПереборСоответствия()
// Создаем соответствие с данными о сотрудниках
Сотрудники = Новый Соответствие;
Сотрудники.Вставить("Иванов", 50000);
Сотрудники.Вставить("Петров", 60000);
Сотрудники.Вставить("Сидоров", 55000);
Сотрудники.Вставить("Кузнецов", 70000);
// Способ 1: перебор по ключам
Сообщить("Перебор по ключам:");
Для Каждого Ключ Из Сотрудники.Ключи() Цикл
Зарплата = Сотрудники.Получить(Ключ);
Сообщить(Ключ + ": " + Зарплата);
КонецЦикла;
// Способ 2: перебор по значениям
Сообщить("Перебор по значениям:");
Для Каждого Значение Из Сотрудники.Значения() Цикл
Сообщить("Зарплата: " + Значение);
КонецЦикла;
// Способ 3: перебор пар "ключ-значение" (рекомендуемый)
Сообщить("Перебор пар ключ-значение:");
Для Каждого Пара Из Сотрудники Цикл
Сообщить(Пара.Ключ + " получает " + Пара.Значение);
КонецЦикла;
КонецПроцедуры
Соответствие как словарь для быстрого поиска
// Использование соответствия для оптимизации поиска в больших данных
Процедура СоответствиеДляБыстрогоПоиска()
// Исходная таблица товаров (1000 записей)
ТаблицаТоваров = Новый ТаблицаЗначений;
ТаблицаТоваров.Колонки.Добавить("Код");
ТаблицаТоваров.Колонки.Добавить("Наименование");
Для Инд = 1 По 1000 Цикл
Строка = ТаблицаТоваров.Добавить();
Строка.Код = "T" + Формат(Инд, "ЧЦ=4; ЧВН=");
Строка.Наименование = "Товар " + Строка(Инд);
КонецЦикла;
// Создаем соответствие для быстрого поиска по коду
ПоисковаяТаблица = Новый Соответствие;
Замер = Новый ЗамерВремени;
Для Каждого Строка Из ТаблицаТоваров Цикл
ПоисковаяТаблица.Вставить(Строка.Код, Строка.Наименование);
КонецЦикла;
ВремяЗаполнения = Замер.Закончить();
Сообщить("Время заполнения соответствия: " + ВремяЗаполнения + " мс");
// Быстрый поиск по ключу
КодПоиска = "T0500";
Замер = Новый ЗамерВремени;
НайденноеНаименование = ПоисковаяТаблица.Получить(КодПоиска);
ВремяПоиска = Замер.Закончить();
Если НайденноеНаименование <> Неопределено Тогда
Сообщить("Найден товар: " + НайденноеНаименование);
Сообщить("Время поиска: " + ВремяПоиска + " мс");
КонецЕсли;
// Сравнение с линейным поиском по таблице
Замер = Новый ЗамерВремени;
Найдено = Неопределено;
Для Каждого Строка Из ТаблицаТоваров Цикл
Если Строка.Код = КодПоиска Тогда
Найдено = Строка.Наименование;
Прервать;
КонецЕсли;
КонецЦикла;
ВремяЛинейногоПоиска = Замер.Закончить();
Сообщить("Время линейного поиска: " + ВремяЛинейногоПоиска + " мс");
КонецПроцедуры
Соответствие для группировки данных
// Использование соответствия для группировки и агрегации данных
Процедура СоответствиеДляГруппировки()
// Исходная таблица продаж
Продажи = Новый ТаблицаЗначений;
Продажи.Колонки.Добавить("Менеджер");
Продажи.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
Продажи.Добавить().Менеджер = "Иванов"; Продажи[0].Сумма = 100000;
Продажи.Добавить().Менеджер = "Петров"; Продажи[1].Сумма = 150000;
Продажи.Добавить().Менеджер = "Иванов"; Продажи[2].Сумма = 80000;
Продажи.Добавить().Менеджер = "Сидоров"; Продажи[3].Сумма = 120000;
Продажи.Добавить().Менеджер = "Иванов"; Продажи[4].Сумма = 90000;
Продажи.Добавить().Менеджер = "Петров"; Продажи[5].Сумма = 70000;
// Группировка через соответствие
ИтогиПоМенеджерам = Новый Соответствие;
Для Каждого СтрокаПродажи Из Продажи Цикл
Менеджер = СтрокаПродажи.Менеджер;
Сумма = СтрокаПродажи.Сумма;
ТекущаяСумма = ИтогиПоМенеджерам.Получить(Менеджер);
Если ТекущаяСумма = Неопределено Тогда
ИтогиПоМенеджерам.Вставить(Менеджер, Сумма);
Иначе
ИтогиПоМенеджерам.Вставить(Менеджер, ТекущаяСумма + Сумма);
КонецЕсли;
КонецЦикла;
// Выводим результаты группировки
Сообщико("Итоги продаж по менеджерам:");
Для Каждого Пара Из ИтогиПоМенеджерам Цикл
Сообщить(Пара.Ключ + ": " + Пара.Значение);
КонецЦикла;
КонецПроцедуры
Соответствие для подсчета количества вхождений
// Подсчет количества повторений элементов с помощью соответствия
Процедура ПодсчетКоличестваВхождений()
// Массив слов для анализа
Слова = Новый Массив;
Слова.Добавить("яблоко");
Слова.Добавить("груша");
Слова.Добавить("яблоко");
Слова.Добавить("слива");
Слова.Добавить("груша");
Слова.Добавить("яблоко");
Слова.Добавить("апельсин");
Слова.Добавить("груша");
// Подсчет с использованием соответствия
Частота = Новый Соответствие;
Для Каждого Слово Из Слова Цикл
ТекущееКоличество = Частота.Получить(Слово);
Если ТекущееКоличество = Неопределено Тогда
Частота.Вставить(Слово, 1);
Иначе
Частота.Вставить(Слово, ТекущееКоличество + 1);
КонецЕсли;
КонецЦикла;
// Вывод результатов
Сообщить("Частота встречаемости слов:");
Для Каждого Пара Из Частота Цикл
Сообщить(Пара.Ключ + ": " + Пара.Значение + " раз(а)");
КонецЦикла;
// Находим самое часто встречающееся слово
МаксимальноеКоличество = 0;
СамоеЧастоеСлово = "";
Для Каждого Пара Из Частота Цикл
Если Пара.Значение > МаксимальноеКоличество Тогда
МаксимальноеКоличество = Пара.Значение;
СамоеЧастоеСлово = Пара.Ключ;
КонецЕсли;
КонецЦикла;
Сообщить("Самое частое слово: " + СамоеЧастоеСлово +
" (" + МаксимальноеКоличество + " раз)");
КонецПроцедуры
Соответствие для кэширования результатов вычислений
// Использование соответствия как кэша для ускорения повторных вычислений
Процедура СоответствиеКакКэш()
Кэш = Новый Соответствие;
// Функция вычисления факториала с кэшированием
Функция ФакториалСКэшем(Число, Кэш)
Если Число <= 1 Тогда
Возврат 1;
КонецЕсли;
// Проверяем, есть ли уже вычисленное значение в кэше
Результат = Кэш.Получить(Число);
Если Результат <> Неопределено Тогда
Сообщить("Использовано кэшированное значение для " + Число);
Возврат Результат;
КонецЕсли;
// Вычисляем и сохраняем в кэш
Результат = Число * ФакториалСКэшем(Число - 1, Кэш);
Кэш.Вставить(Число, Результат);
Возврат Результат;
КонецФункции
// Тестируем с замером времени
Замер = Новый ЗамерВремени;
Для Инд = 1 По 10 Цикл
Результат = ФакториалСКэшем(5, Кэш);
КонецЦикла;
ВремяСКэшем = Замер.Закончить();
Сообщить("Время 10 вычислений с кэшем: " + ВремяСКэшем + " мс");
Сообщить("Размер кэша: " + Кэш.Количество() + " элементов");
// Очищаем кэш
Кэш.Очистить();
Замер = Новый ЗамерВремени;
Для Инд = 1 По 10 Цикл
Результат = ФакториалСКэшем(5, Кэш);
КонецЦикла;
ВремяБезКэша = Замер.Закончить();
Сообщить("Время 10 вычислений без кэша: " + ВремяБезКэша + " мс");
КонецПроцедуры
Преобразование таблицы значений в соответствие
// Преобразование таблицы значений в соответствие для удобного доступа
Процедура ТаблицаВСоответствие()
// Исходная таблица
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Код");
Таблица.Колонки.Добавить("Наименование");
Таблица.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
Таблица.Добавить().Код = "001"; Таблица[0].Наименование = "Ноутбук"; Таблица[0].Цена = 50000;
Таблица.Добавить().Код = "002"; Таблица[1].Наименование = "Монитор"; Таблица[1].Цена = 15000;
Таблица.Добавить().Код = "003"; Таблица[2].Наименование = "Клавиатура"; Таблица[2].Цена = 2000;
Таблица.Добавить().Код = "004"; Таблица[3].Наименование = "Мышь"; Таблица[3].Цена = 1000;
// Преобразование: ключ - код, значение - строка таблицы
ТаблицаПоКоду = Новый Соответствие;
Для Каждого Строка Из Таблица Цикл
ТаблицаПоКоду.Вставить(Строка.Код, Строка);
КонецЦикла;
// Быстрый доступ по коду
КодПоиска = "003";
НайденнаяСтрока = ТаблицаПоКоду.Получить(КодПоиска);
Если НайденнаяСтрока <> Неопределено Тогда
Сообщить("Найден товар с кодом " + КодПоиска + ":");
Сообщить(" Наименование: " + НайденнаяСтрока.Наименование);
Сообщить(" Цена: " + НайденнаяСтрока.Цена);
КонецЕсли;
// Преобразование: ключ - наименование, значение - цена
ЦеныПоНаименованию = Новый Соответствие;
Для Каждого Строка Из Таблица Цикл
ЦеныПоНаименованию.Вставить(Строка.Наименование, Строка.Цена);
КонецЦикла;
Сообщить("Цена монитора: " + ЦеныПоНаименованию.Получить("Монитор"));
КонецПроцедуры
Сравнение и объединение соответствий
// Операции сравнения и объединения двух соответствий
Процедура СравнениеИОбъединениеСоответствий()
// Соответствие 1: цены поставщика А
ЦеныА = Новый Соответствие;
ЦеныА.Вставить("Ноутбук", 50000);
ЦеныА.Вставить("Монитор", 15000);
ЦеныА.Вставить("Клавиатура", 2000);
ЦеныА.Вставить("Мышь", 1000);
// Соответствие 2: цены поставщика Б
ЦеныБ = Новый Соответствие;
ЦеныБ.Вставить("Ноутбук", 48000);
ЦеныБ.Вставить("Монитор", 16000);
ЦеныБ.Вставить("Принтер", 25000);
ЦеныБ.Вставить("Сканер", 12000);
// Поиск общих ключей и сравнение цен
Сообщить("Сравнение цен у разных поставщиков:");
Для Каждого КлючА Из ЦеныА.Ключи() Цикл
ЦенаБ = ЦеныБ.Получить(КлючА);
Если ЦенаБ <> Неопределено Тогда
ЦенаА = ЦеныА.Получить(КлючА);
Разница = ЦенаА - ЦенаБ;
Сообщить(КлючА + ": " + ЦенаА + " vs " + ЦенаБ +
" (разница: " + Разница + ")");
КонецЕсли;
КонецЦикла;
// Объединение соответствий (цены из обоих источников)
ОбъединенныеЦены = Новый Соответствие;
// Добавляем все цены из А
Для Каждого Пара Из ЦеныА Цикл
ОбъединенныеЦены.Вставить(Пара.Ключ, Пара.Значение);
КонецЦикла;
// Добавляем цены из Б, если ключа еще нет
Для Каждого Пара Из ЦеныБ Цикл
Если Не ОбъединенныеЦены.КлючСуществует(Пара.Ключ) Тогда
ОбъединенныеЦены.Вставить(Пара.Ключ, Пара.Значение);
КонецЕсли;
КонецЦикла;
Сообщить("Объединенный ассортимент:");
Для Каждого Пара Из ОбъединенныеЦены Цикл
Сообщить(Пара.Ключ + ": " + Пара.Значение);
КонецЦикла;
// Поиск уникальных для каждого поставщика
Сообщить("Товары только у поставщика А:");
Для Каждого КлючА Из ЦеныА.Ключи() Цикл
Если Не ЦеныБ.КлючСуществует(КлючА) Тогда
Сообщить(КлючА);
КонецЕсли;
КонецЦикла;
Сообщить("Товары только у поставщика Б:");
Для Каждого КлючБ Из ЦеныБ.Ключи() Цикл
Если Не ЦеныА.КлючСуществует(КлючБ) Тогда
Сообщить(КлючБ);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Соответствие как мультисловарь (один ключ — несколько значений)
// Хранение нескольких значений по одному ключу с помощью соответствия
Процедура СоответствиеКакМультисловарь()
// Соответствие, где значение - массив
СтудентыПоГруппам = Новый Соответствие;
// Функция добавления студента в группу
Процедура ДобавитьСтудента(Группа, Студент, Соответствие)
МассивСтудентов = Соответствие.Получить(Группа);
Если МассивСтудентов = Неопределено Тогда
МассивСтудентов = Новый Массив;
Соответствие.Вставить(Группа, МассивСтудентов);
КонецЕсли;
МассивСтудентов.Добавить(Студент);
КонецПроцедуры
// Добавляем студентов
ДобавитьСтудента("Группа 1", "Иванов", СтудентыПоГруппам);
ДобавитьСтудента("Группа 1", "Петров", СтудентыПоГруппам);
ДобавитьСтудента("Группа 2", "Сидоров", СтудентыПоГруппам);
ДобавитьСтудента("Группа 1", "Кузнецов", СтудентыПоГруппам);
ДобавитьСтудента("Группа 2", "Смирнов", СтудентыПоГруппам);
ДобавитьСтудента("Группа 3", "Васильев", СтудентыПоГруппам);
// Выводим всех студентов по группам
Сообщить("Список студентов по группам:");
Для Каждого Группа Из СтудентыПоГруппам Цикл
Сообщить(Группа.Ключ + ":");
МассивСтудентов = Группа.Значение;
Для Каждого Студент Из МассивСтудентов Цикл
Сообщить(" - " + Студент);
КонецЦикла;
КонецЦикла;
// Функция получения количества студентов в группе
Функция КоличествоСтудентов(Группа, Соответствие)
МассивСтудентов = Соответствие.Получить(Группа);
Если МассивСтудентов = Неопределено Тогда
Возврат 0;
КонецЕсли;
Возврат МассивСтудентов.Количество();
КонецФункции
Сообщить("В группе 1 студентов: " + КоличествоСтудентов("Группа 1", СтудентыПоГруппам));
КонецПроцедуры
Соответствие для реализации графа (связи между объектами)
// Использование соответствия для хранения связей (граф)
Процедура СоответствиеКакГраф()
// Создаем граф связей между сотрудниками
ГрафСвязей = Новый Соответствие;
// Добавляем связи
Процедура ДобавитьСвязь(ОтКого, Кому, Граф)
Связи = Граф.Получить(ОтКого);
Если Связи = Неопределено Тогда
Связи = Новый Массив;
Граф.Вставить(ОтКого, Связи);
КонецЕсли;
Связи.Добавить(Кому);
КонецПроцедуры
ДобавитьСвязь("Иванов", "Петров", ГрафСвязей);
ДобавитьСвязь("Иванов", "Сидоров", ГрафСвязей);
ДобавитьСвязь("Петров", "Кузнецов", ГрафСвязей);
ДобавитьСвязь("Сидоров", "Петров", ГрафСвязей);
ДобавитьСвязь("Кузнецов", "Смирнов", ГрафСвязей);
// Функция поиска всех связей (соседей) для сотрудника
Функция НайтиСвязи(Сотрудник, Граф)
Результат = Новый Массив;
Связи = Граф.Получить(Сотрудник);
Если Связи <> Неопределено Тогда
Для Каждого Связь Из Связи Цикл
Результат.Добавить(Связь);
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция поиска всех связей на глубину
Функция НайтиСвязиНаГлубину(Сотрудник, Граф, Глубина = 1)
Результат = Новый Массив;
Посещенные = Новый Соответствие;
РекурсивныйПоиск(Сотрудник, Глубина, 0, Результат, Посещенные, Граф);
Возврат Результат;
КонецФункции
Процедура РекурсивныйПоиск(Сотрудник, МаксГлубина, ТекущаяГлубина, Результат, Посещенные, Граф)
Если ТекущаяГлубина >= МаксГлубина Тогда
Возврат;
КонецЕсли;
Посещенные.Вставить(Сотрудник, Истина);
Связи = Граф.Получить(Сотрудник);
Если Связи <> Неопределено Тогда
Для Каждого Связь Из Связи Цикл
Результат.Добавить(Связь);
Если Посещенные.Получить(Связь) = Неопределено Тогда
РекурсивныйПоиск(Связь, МаксГлубина, ТекущаяГлубина + 1, Результат, Посещенные, Граф);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Тестируем
СвязиИванова = НайтиСвязи("Иванов", ГрафСвязей);
Сообщить("Непосредственные связи Иванова:");
Для Каждого Связь Из СвязиИванова Цикл
Сообщить(" - " + Связь);
КонецЦикла;
ВсеСвязиИванова = НайтиСвязиНаГлубину("Иванов", ГрафСвязей, 2);
Сообщить("Все связи Иванова на глубину 2:");
Для Каждого Связь Из ВсеСвязиИванова Цикл
Сообщить(" - " + Связь);
КонецЦикла;
КонецПроцедуры
Сериализация и десериализация соответствия
// Сохранение соответствия в строку и восстановление
Процедура СериализацияСоответствия()
// Исходное соответствие
Исходное = Новый Соответствие;
Исходное.Вставить("Ключ1", "Значение1");
Исходное.Вставить("Ключ2", 12345);
Исходное.Вставить("Ключ3", ТекущаяДата());
Исходное.Вставить("Ключ4", Новый Структура("Поле1, Поле2", "Данные1", "Данные2"));
// Сериализация в строку XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("Соответствие");
Для Каждого Пара Из Исходное Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("Пара");
ЗаписьXML.ЗаписатьАтрибут("Ключ", Пара.Ключ);
// Сохраняем тип значения
ТипЗначения = ТипЗнч(Пара.Значение);
ЗаписьXML.ЗаписатьАтрибут("Тип", Строка(ТипЗначения));
// Сохраняем значение
ЗаписьXML.ЗаписатьТекст(Строка(Пара.Значение));
ЗаписьXML.ЗаписатьКонецЭлемента(); // Пара
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента(); // Соответствие
СтрокаXML = ЗаписьXML.Закрыть();
Сообщить("Сериализованное соответствие:");
Сообщить(СтрокаXML);
// Десериализация
Восстановленное = Новый Соответствие;
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
ЧтениеXML.Прочитать();
ЧтениеXML.Прочитать();
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Пара" Тогда
Ключ = ЧтениеXML.ПолучитьАтрибут("Ключ");
ТипСтрока = ЧтениеXML.ПолучитьАтрибут("Тип");
ЧтениеXML.Прочитать();
ЗначениеСтрока = ЧтениеXML.Значение;
// Восстанавливаем значение с учетом типа
Значение = ВосстановитьЗначениеПоТипу(ЗначениеСтрока, ТипСтрока);
Восстановленное.Вставить(Ключ, Значение);
КонецЕсли;
КонецЦикла;
Сообщить("Восстановленное соответствие:");
Для Каждого Пара Из Восстановленное Цикл
Сообщить(Пара.Ключ + " = " + Строка(Пара.Значение));
КонецЦикла;
КонецПроцедуры
Функция ВосстановитьЗначениеПоТипу(ЗначениеСтрока, ТипСтрока)
Если ТипСтрока = "Дата" Тогда
Возврат Дата(ЗначениеСтрока);
ИначеЕсли ТипСтрока = "Число" Тогда
Возврат Число(ЗначениеСтрока);
ИначеЕсли ТипСтрока = "Булево" Тогда
Возврат ?(ЗначениеСтрока = "Да", Истина, Ложь);
Иначе
Возврат ЗначениеСтрока;
КонецЕсли;
КонецФункции
Примечания
// Важные особенности работы с соответствием:
// 1. Соответствие обеспечивает быстрый доступ к данным по ключу (O(1) в среднем)
// 2. Ключи могут быть любого типа, но должны быть уникальными
// 3. Для перебора пар используйте цикл Для Каждого Пара Из Соответствие
// 4. Метод КлючСуществует() проверяет наличие ключа без получения значения
// 5. При вставке существующего ключа старое значение заменяется новым
// 6. Соответствие не гарантирует порядок элементов при переборе
// 7. Для хранения нескольких значений по ключу используйте массив в качестве значения
// 8. Соответствие эффективно для группировки и подсчета частоты
// 9. При работе с большими данными соответствие быстрее таблицы значений для поиска
// 10. Соответствие можно использовать как кэш для ускорения повторных вычислений
// 11. Для сериализации соответствия используйте XML или JSON (через ЗаписьJSON)
// 12. Метод Очистить() удаляет все элементы, Количество() возвращает размер








