Как готовить и есть массивы

24.01.24

Разработка - Механизмы платформы 1С

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

Содержание

 

Создание массива

Не хочу утомлять долгими предисловиями, сразу к делу.

Существует 3 способа объявить новый массив.

Массив = Новый Массив;

Это самый распространенный способ создания простого пустого массива.

 
 Пруф

Далее, создание массива по количеству элементов:

Массив = Новый Массив(3);

Создает новый массив и добавляет в него 3 элемента "Неопределено"

 
 Пруф

Есть "грязный хак", которым не стоит пользоваться, но надо знать о его существовании. Переданное значение в конструктор будет приведено к числу насильно:

Массив = Новый Массив("5");
 
 Пруф
Массив = Новый Массив(Истина);
 
 Пруф

Конструкции типа:

Массив = Новый Массив(0);
Массив = Новый Массив(Ложь);

Вызовут исключение "Ошибка при вызове конструктора (Массив)"    

Также можно создать многомерный массив из конструктора:

Массив = Новый Массив(2, 3, 4);

Такая конструкция создаст массив с 2 элементами, которые в свою очередь будут массивами с 3 элементами внутри, которые в свою очередь будут массивами с 4 элементами "Неопределено"

 
 Пруф

Ну и массив можно создать на основании фиксированного массива, но об этом чуть позже.

 

Добавление элементов

Как можно добавлять элементы в массив.

Массив = Новый Массив;
Массив.Добавить("Какой-то элемент №0");
Массив.Добавить("Какой-то элемент №1");
Массив.Добавить("Какой-то элемент №2");
Массив.Добавить("Какой-то элемент №3");
Массив.Добавить("Какой-то элемент №4");

Самый распространенный способ - это вызвать метод массива "Добавить". Код, приведенный выше, добавит 5 элементов в массив. Обратите внимание, что индексы массива начинаются с 0. А это значит, что при выполнении кода выше, количество элементов будет 5, а максимальный индекс - 4.

 
 Пруф
Массив = Новый Массив;
Массив.Вставить(3, "Какой-то элемент №0");
Массив.Вставить(7, "Какой-то элемент №1");

Метод массива "Вставить" добавляет элемент по указанному индексу. Код выше инициирует пустой массив и вставляет по индексам 3 и 7 два элемента. Но в пустом массиве нет никаких элементов по указанным индексам. На этот случай платформа делает так

 
 Пруф

Она просто создает элементы до указанного индекса, заполняя пустые элементы значением "Неопределено". Если мы попытаемся вставить в этот массив какое-то значение по индексу 5:

Массив = Новый Массив;
Массив.Вставить(3, "Какой-то элемент №0");
Массив.Вставить(7, "Какой-то элемент №1");
Массив.Вставить(5, "Какой-то элемент №2");
 
 Пруф

То платформа не установит в указанный индекс значение, а сдвинет его. То есть значение по индексу 5 перейдет на 6, и т.д. Давайте попробуем вставить значение по индексу 8:

Массив = Новый Массив;
Массив.Вставить(3, "Какой-то элемент №0");
Массив.Вставить(7, "Какой-то элемент №1");
Массив.Вставить(5, "Какой-то элемент №2");
Массив.Вставить(8, "Какой-то элемент №3");
 
 Пруф

Как видно из скрина, "Какой-то элемент №1" переехал на строку с индексом 9, а его место заняло то значение, которое мы вставили.

Так же мы можем не указывать значение, которое хотим вставить:

Массив = Новый Массив;
Массив.Вставить(3, "Какой-то элемент №0");
Массив.Вставить(7, "Какой-то элемент №1");
Массив.Вставить(5, "Какой-то элемент №2");
Массив.Вставить(8, "Какой-то элемент №3");
Массив.Вставить(10);

И получим новый элемент массива со значением "Неопределено"

 
 Пруф

И конечно, тут тоже можно устроить вакханалию с приведением типа значения, передаваемого в индекс, к числу:

Массив = Новый Массив;          
Массив.Вставить(Ложь, "Ложь");
Массив.Вставить(Истина, "Истина"); 
Массив.Вставить("2", "2");
 
 Пруф

 

Разные количества

Теперь поработаем с числами

Для примера будем брать массив

 
 Массив для примера

Посчитаем количество элементов, для этого вызовем метод:

Массив.Количество();
 
 Пруф

В ответ нам возвращается число с количеством элементов. А как узнать самый большой индекс в массиве? Поскольку количество считаем мы от 1, а индекс идет от 0, многим кажется хорошим решением вызвать такую конструкцию:

Массив.Количество() - 1;

Но разработчики платформы любезно предоставили нам метод:

Массив.ВГраница();
 
 Пруф

 

Получение данных

Попробуем получить данные из массива.

Обход массива в цикле оставим на десерт, а сейчас глянем на методы массива. 

Для примера возьмем массив

 
 Совершенно другой массив для примера

В конец массива мы добавили такое же значение, что и по индексу 3

Итак, попробуем найти значение "Какой-то элемент №3":

Массив.Найти("Какой-то элемент №3");
 
 Пруф

Массив не сообщает нам о том, что у него есть 2 одинаковых элемента, он просто отдает индекс первого попавшегося от начала массива

Если мы ищем значение, которого в массиве нет:

Массив.Найти("Какой-то элемент №10")

То получим значение "Неопределено"

 
 Пруф

Если нам известен индекс, и мы хотим получить значение, можно вызвать:

Массив.Получить(2);
 
 Пруф

Если мы попытаемся передать сюда индекс, которого нет в массиве, получим исключение "Ошибка при вызове метода контекста (Получить)"

Так же мы можем получить элемент массива по индексу, используя конструкцию:

Массив[4]
 
 Пруф

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

Ну и по классике, такой говнокод будет работать

Массив.Получить(Истина);
Массив.Получить(Ложь);
Массив.Получить("2");

А вот с квадратными скобками такой финт не прокатит, и вы получите исключение

 

Редактирование данных

Теперь попробуем заменить какой-нибудь элемент массива. Для примера опять же возьмем массив

 
 Абсолютно другой массив для примера

И вызовем метод 

Массив.Установить(3, "Какой-то новый элемент №3");

Этот метод не будет двигать строки массива, он просто подменит элемент по указанному индексу на тот, что вы передали

 
 Пруф

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

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

Массив[3] = "Какой-то новый элемент №3";

Такой код тоже будет работать.

 

Удаление элементов

Метод: 

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

не принимает никаких параметров, а просто удаляет все элементы из массива.

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

 
 Вообще новый массив для примера

И вызовем метод 

Массив.Удалить(2);

И увидим, что элемента действительно в массиве больше нет

 
 Пруф

То есть индекс 2 остался, но строки массива после индекса 1 сдвинулись на одну назад, чтобы не было пустот после удаления

 

Работа с массивом

Теперь немного про обход массива в цикле.

Мы можем обойти массив по элементам:

Для Каждого Элемент Из Массив Цикл
   // тут что-то делаем с элементом
КонецЦикла;

Тогда в переменную попадает сам элемент, не строка с массивом, а именно элемент со всеми оттуда вытекающими. То есть, имея массив документов, можно сделать так:

Для Каждого Документ Из МассивДокументов Цикл
   Документ.Записать();
КонецЦикла;

Еще мы можем обойти массив по индексам

Для Индекс = 0 По Массив.ВГраница() Цикл
   Массив[Индекс] // тут что-то делаем с элементом массива
   Массив.Получить(Индекс) // тут тоже что-то делаем с элементом массива
   Массив.Получить(Строка(Индекс)) // и тут тоже что-то можно делать с элементом, но лучше не стоит
КонецЦикла;

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

Для Счет = 0 По Массив.Количество() - 1 Цикл
   Массив[Счет] // тут что-то делаем с элементом массива
КонецЦикла

Мы можем обойти цикл с конца

Для Индекс = 0 По Массив.ВГраница() Цикл
   Массив[Массив.ВГраница() - Индекс] // тут что-то делаем с элементом массива
КонецЦикла;

// Добавил SerVer1C
Для Индекс = -Массив.ВГраница() По 0 Цикл
   Массив[-Индекс] // тут что-то делаем с элементом массива
КонецЦикла;

Но, при обходе массива в цикле, не советую изменять массив методами, меняющими количество элементов массива. Давайте попробуем в нашем массиве для примера заменить все значения, а элемент по индексу 3 удалить.

Массив = Новый Массив;
Массив.Добавить("Какой-то элемент №0");
Массив.Добавить("Какой-то элемент №1");
Массив.Добавить("Какой-то элемент №2");
Массив.Добавить("Какой-то элемент №3");
Массив.Добавить("Какой-то элемент №4");

Для Индекс = 0 По Массив.ВГраница() Цикл
	Если Индекс = 3 Тогда
		Массив.Удалить(Индекс);
	КонецЕсли;
   Массив[Индекс] = СтрЗаменить(Массив[Индекс], "элемент", "новый элемент");
КонецЦикла;

Выполнение этого кода вызовет исключение потому, что вы обходите массив до индекса 4, но в моменте удаляете элемент с индексом 3, а значит элемент с индексом 4 сдвигается на 1 строку назад, и при попытке изменить элемент по индексу 4, вы получите что-то типа "Индекс находится за границами массива". Все изменения, связанные с изменением количества элементов массива, надо сделать вне цикла (то есть до или после);

Для адекватного удаления элементов массива в цикле по условию, нужно обходить массив в обратном порядке. Вариант шаблона zqzq:

Для Индекс = 1 - <?"Коллекция">.Количество() По 0 Цикл
    <?"Элемент коллекции"> = <?"Коллекция">[-Индекс];
    Если <?> Тогда
        <?"Коллекция">.Удалить(<?"Элемент коллекции">);
    КонецЕсли;
КонецЦикла;

 

Вы можете удалить нежелательные элементы из массива в цикле

Массив = Новый Массив;          
Массив.Вставить(4, "Какой-то элемент №4");
Массив.Вставить(7, "Какой-то элемент №7"); 
// как вы помните, элементы по индексам 0,1,2,3,5,6 будут со значением "Неопределено". Удалим их все.
Пока Массив.Найти(Неопределено) <> Неопределено Цикл
	Элемент = Массив.Найти(Неопределено);
	Массив.Удалить(Элемент);
КонецЦикла;
 
 Пруф

Теперь попробуем удалить дубли из массива

Массив = Новый Массив;
Массив.Добавить("Какой-то элемент №0");
Массив.Добавить("Какой-то элемент №4");
Массив.Добавить("Какой-то элемент №1");
Массив.Добавить("Какой-то элемент №4");
Массив.Добавить("Какой-то элемент №2");
Массив.Добавить("Какой-то элемент №4");
Массив.Добавить("Какой-то элемент №3");
Массив.Добавить("Какой-то элемент №4");

НовыйМассив = Новый Массив;
Для Каждого Элемент Из Массив Цикл
	Если НовыйМассив.Найти(Элемент) = Неопределено Тогда
		НовыйМассив.Добавить(Элемент);
	КонецЕсли;
КонецЦикла;
 
 Пруф

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

Ну и на финал немного про фиксированный массив. Фиксированный массив, это такой массив, в котором нет методов "Вставить", "Добавить", "Очистить", "Удалить" и "Установить". Но если в массив нельзя добавить элемент, как его наполнить? Вся соль в том, что он создается на основании обычного массива

Массив = Новый Массив;
Массив.Добавить("Какой-то элемент №0");
Массив.Добавить("Какой-то элемент №1");
Массив.Добавить("Какой-то элемент №2");
Массив.Добавить("Какой-то элемент №3");
Массив.Добавить("Какой-то элемент №4");

ФиксированныйМассив = Новый ФиксированныйМассив(Массив);

Все, теперь при изменении такого массива вы будете ловить исключения. Если же вам очень нужно в таком массиве что-то изменить, вы можете создать обычный массив на основании фиксированного

Массив = Новый Массив;
Массив.Добавить("Какой-то элемент №0");
Массив.Добавить("Какой-то элемент №1");
Массив.Добавить("Какой-то элемент №2");
Массив.Добавить("Какой-то элемент №3");
Массив.Добавить("Какой-то элемент №4");

ФиксированныйМассив = Новый ФиксированныйМассив(Массив);

НовыйМассив = Новый Массив(ФиксированныйМассив);

И все, теперь у вас есть обычный массив, имеющий те же данные, что в фиксированном, но с возможностью изменения.

 

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

А так же смотрите другие мои публикации

Генерация штрихкода и QR, разбор настроек и примеры

Валидация JSON через XDTO (включая массивы)

Отправка документа без сохранения в файл (ПотокВПамяти)

массив язык программирование уроки обучение вграница вставить фиксированный

См. также

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    7400    bayselonarrend    19    

154

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    5934    dsdred    16    

80

Перенос данных 1C Механизмы платформы 1С Системный администратор Программист Стажер Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    11206    dsdred    44    

130

Механизмы платформы 1С Программист Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    23744    SeiOkami    48    

135

Механизмы платформы 1С Системный администратор Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    18804    human_new    27    

80

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

28.08.2023    14721    YA_418728146    7    

166

Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    8370    sebekerga    55    

104
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. SerVer1C 815 24.01.24 17:31 Сейчас в теме
Мы можем обойти цикл с конца

Для Индекс = -Массив.ВГраница() По 0 Цикл
   Массив[-Индекс] // тут что-то делаем с элементом массива
КонецЦикла;
Abris9; lostcay; kser87; nemec; shard; BigB; acvatoris; maksa2005; SP2000; starik-2005; stephanevigroux; YA_418728146; +12 Ответить
5. kalyaka 1105 25.01.24 10:09 Сейчас в теме
(1) Отрицательный индекс в 1С не допускается. Такое допускается в других языках, например в JS - и там это индекс с конца.
6. SerVer1C 815 25.01.24 10:13 Сейчас в теме
(5) Смотрите внимательнее код!
Abris9; Риник; it-expertise; +3 Ответить
9. kalyaka 1105 25.01.24 10:21 Сейчас в теме
(6)Ок! Действительно, оригинально :)
Для тех, кто такой же невнимательный как я, индекс здесь положительный (верхняя граница берется со знаком "-").
2. serg-lom89 76 24.01.24 20:47 Сейчас в теме
Спасибо.
Вроде все и так известно но пришлось пробежаться - освежить)
3. dhurricane 25.01.24 02:10 Сейчас в теме
Вот со вставкой в массив с автодополнением оказался сюрприз-сюрприз. Всегда был уверен, что можно вставлять без ошибок лишь в позицию, равную количеству элементов в массиве, что приведет к банальному добавлению нового элемента в конец массива. Но такое... СП не читал, я даже предположить не мог, что разработчикам платформы придет в голову такая реализация. Спасибо за открытие.
4. zqzq 25 25.01.24 09:16 Сейчас в теме
Утомляет, что нет человеческого конструктора массива по значениям, как в современных языках (в том же 1С:Исполнителе есть).

Сделал себе сам для небольших массивов:
Функция НовыйМассив(  П1 = Неопределено,  П2 = Неопределено,  П3 = Неопределено
					, П4 = Неопределено,  П5 = Неопределено,  П6 = Неопределено
					, П7 = Неопределено,  П8 = Неопределено,  П9 = Неопределено
					, П10 = Неопределено, П11 = Неопределено, П12 = Неопределено
					, П13 = Неопределено, П14 = Неопределено, П15 = Неопределено					
) Экспорт 
		
	ВСЕГО_АРГУМЕНТОВ = 15;
	
	Рез = Новый Массив;
	Для Инд = 1 По ВСЕГО_АРГУМЕНТОВ Цикл
		Выполнить("
		|Если П" + Инд + " <> Неопределено Тогда
		|	Рез.Добавить(П" + Инд + ");
		|КонецЕсли;
		|");
	КонецЦикла; 
		
	Возврат Рез;
		
КонецФункции
Показать
DENSKR; asupsam; +2 Ответить
21. AntonProgma 48 28.01.24 08:30 Сейчас в теме
(4)
НовыйМассив(1, 2, , 4) вернёт массив из трех элементов -- [1, 2, 4]. Интуитивно ожидается [1, 2, Неопределено, 4]
22. AntonProgma 48 28.01.24 08:44 Сейчас в теме
(4) конечно, в 1С очень много кода требуется, чтобы создать массив и заполнить его произвольными элементами. Поэтому я тоже использую похожие функции для простых случаев создания универсальных коллекций одной командой. Выглядит так:

__.Массив(значение1, значение2, ..., значение30)

__.Соответствие(
"ключ1", значение1,
"ключ2", значение2,
...
)

Запись удобнее пока не придумал.
7. artbear 1563 25.01.24 10:15 Сейчас в теме
Хорошая статья, спасибо!

небольшая ошибка с Индекс или Счет

Для Счет = 0 По Массив.Количество() - 1 Цикл
Массив[Индекс] // тут что-то делаем с элементом массива
КонецЦикла
YA_418728146; +1 Ответить
8. kalyaka 1105 25.01.24 10:17 Сейчас в теме
Для инициализации массива строковых значений можно использовать функцию СтрРазделить().

Еще, для продвинутых, можно инициализировать массив из JSON через использование функции БСП
Код
Коэффициенты = ОбщегоНазначения.JSONВЗначение("[1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3]");
Показать полностью
.
dabu-dabu; ya.Avoronov; dfgdsfgsdfg2011; asupsam; +4 Ответить
10. user1983561 25.01.24 11:54 Сейчас в теме
1. Пытался как-то создать, двухмерный динамический массив?

ДвухмерныйМассив = Новый Массив (, 2);
ДвухмерныйМассив = Новый Массив (0, 2);

Так и не получилось!

2. Также в таком массиве не работает метод Найти()

3. Пытался присваивать или получать значения так
ДвухмерныйМассив[0][0]
ДвухмерныйМассив[0][1]

то же не получалось
11. YA_418728146 584 25.01.24 12:38 Сейчас в теме
(10) Что значит динамический?

Сделай
ДвухмерныйМассив = Новый Массив (1, 2);

И обращайся к нему
ДвухмерныйМассив[0][0]
ДвухмерныйМассив[0][1]
ДвухмерныйМассив[0][2]
viktor3d; +1 Ответить
12. capitan 2507 25.01.24 19:05 Сейчас в теме
1Сники не сортируют пузырьками, они пузырьками употребляют, пардон муа за каламбур
Они делают списокзначений.загрузитьзначения, сортироватьпозначению, выгрузить значения )
NoRazum; volokitinac; smit1c; zqzq; Bassgood; shard; SerVer1C; YA_418728146; acvatoris; +9 Ответить
15. kalyaka 1105 26.01.24 10:34 Сейчас в теме
(12)Конечно, когда речь идет
про знания алгоритмов, которыми 1С-ники пользуются чуть чаще, чем никогда
:)
19. capitan 2507 26.01.24 12:46 Сейчас в теме
(15)у каждого свои алгоритмы
На флоте электрики говорят: Закон Ома - три года и дома :)
20. mszsuz 335 27.01.24 17:49 Сейчас в теме
А что за название вГраница()?

Решил спросить мнение у chatGPT, почему метод назвали ВГраница(), а не, например, Размер()?
Вот что выдал стендап-электроник:

- Почему метод называется вГраница(), а не Размер()? Потому что в программировании, как и в отношениях, иногда важнее знать, где заканчивается, чем насколько большой!

ещё вариант:

- Почему метод вГраница(), а могли ведь назвать и ПростоКонец()? Потому что в мире программирования даже при завершении массива хочется сохранить интригу — вдруг это не просто конец, а начало нового приключения?

ПростоКонец() или Конец(), кстати, хорошо бы вписался в семантику и лично у меня бы не было вопросов.
user1734848; NoRazum; user632212; artbear; +4 Ответить
25. eden_gmail 29.01.24 06:43 Сейчас в теме
13. TMV 14 26.01.24 06:44 Сейчас в теме
Все изменения, связанные с изменением количества элементов массива, надо сделать вне цикла (то есть до или после);
В приведенном примере можно удалить элемент в цикле, если обходить его с конца.
17. пользователь 26.01.24 11:50
Сообщение было скрыто модератором.
...
14. capitan 2507 26.01.24 10:09 Сейчас в теме
И еще для полноты рассказа не хватает примера как массив положить сам в себя и отправить это на сервер ;)
16. kalyaka 1105 26.01.24 10:43 Сейчас в теме
(14)ну это другая тема, это ж не только массивы так можно замкнуть, но и любые структуры. Это про передачу по значению или по ссылке и про сериализацию этого.
18. capitan 2507 26.01.24 12:44 Сейчас в теме
(16)чегой то другая?
это как раз то чего не хватает в статье - как массив хранится и как сериализуется
это будет интересно больше, чем из справки выдержки
23. ltfriend 28.01.24 12:45 Сейчас в теме
А что такое "пруф"?
Jimbo; kser87; +2 Ответить
24. n_mezentsev 57 28.01.24 14:58 Сейчас в теме
(23)Это из зарубежной юриспруденции - основной инструмент прокурора) Как там в "Красной жаре" - "Какие ваши доказательства"©️
26. kser87 2470 29.01.24 12:52 Сейчас в теме
(23) proof по-английски доказательство. proove - доказать. Используется в математике, физики и других дисциплинах в значении, аналогичном "требуется доказать теорему" и тд
27. Gesperid 2 28.08.24 15:26 Сейчас в теме
Найти - медленная операция, т.к. просматривается ВГраница() элементов в худшем случае.
Использовать многократно, например в цикле - нежелательно.
Массив лучше заменить на Соответствие или ТаблицуЗначений с индексированными колонками. Подробнее можно почитать стандарт #std452

Аналогично с методом Удалить().
e9504100606; +1 Ответить
Оставьте свое сообщение