Как правильно удалять данные из больших массивов

15.02.21

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

Как правильно удалять данные из больших несортированных массивов

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

Наименование Файл Версия Размер
Как правильно удалять данные из больших массивов:
.epf 7,50Kb
0
.epf 7,50Kb Скачать

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

Массив = СгенерироватьМассив(мэлементов); 
                              
Функция СгенерироватьМассив(КоличествоЭлементов)        
    ГенераторСлучайныхЧисел = новый ГенераторСлучайныхЧисел;      
    Массив = Новый Массив;          
    Для Индекс = 1 По КоличествоЭлементов Цикл                          
        Массив.Добавить(ГенераторСлучайныхЧисел.СлучайноеЧисло(0,200) - 100);                 
    КонецЦикла;   
    Возврат Массив;
КонецФункции

Большая часть людей делает это так:


Для обратныйИндекс = - Массив.ВГраница() По 0 Цикл
   Индекс = - обратныйИндекс;
   Если Не Условие1(Массив[Индекс]) Тогда
      Массив.Удалить(Индекс);        
   КонецЕсли;
КонецЦикла;

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


Для Индекс = УдаляемыйИндекс По Массив.ВГраница() - 1 Цикл
   Массив[Индекс] = Массив[Индекс + 1];            
КонецЦикла;

Из этого следует что мы выполняем цикл в цикле.

 

Верным же способом удаления данных из массива можно назвать вот такой метод:


МаксимальныйИндекс = -1;
Для Каждого ЭлМассва Из Массив Цикл
   Если Условие1(ЭлМассва) Тогда
      МаксимальныйИндекс = МаксимальныйИндекс + 1;
      Массив[МаксимальныйИндекс] = ЭлМассва;                                                
   КонецЕсли;       
КонецЦикла;
Пока Массив.ВГраница() > МаксимальныйИндекс Цикл
   Массив.Удалить(Массив.ВГраница());               
КонецЦикла;

 

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

Важное замечание: данное рассуждение актуально только для несортированных массивов, или сортированных массивов, удаляемые значения которых будут находится в начале массива.

Во вложении обработка, показывающая график с разницей по времени выполнения обоих способов (по вертикали – время в МС, по горизонтали – количество элементов). Обработка работает на управляемых формах для любых версий платформы 8.3.

В случае с вторым алгоритмом – график прямолинейный, в случае с первым – квадратичный (не совсем, но если кому интересно, может вывести верную формулу, одной из переменных которой нужно указать процент удаляемых данных)

удаление из массивов

См. также

Вставляем картинку из буфера обмена (платформа 1С 8.3.24)

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

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

1 стартмани

18.03.2024    2677    0    John_d    8    

55

GUID в 1С 8.3 - как с ними быть

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

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

12.02.2024    4613    atdonya    22    

45

Переоткрытие внешних обработок

Универсальные функции Платформа 1С v8.3 Бесплатно (free)

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

30.11.2023    3963    ke.92@mail.ru    16    

61

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

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

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

28.08.2023    8841    YA_418728146    6    

141

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2077    21    progmaster    7    

3

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    16150    133    sapervodichka    112    

129

Система контроля ведения учета [БСП]

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

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    7243    quazare    8    

109
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. starik-2005 3033 15.02.21 11:40 Сейчас в теме
А не проще тогда просто найти элемент массива "МойМассив.Найти( Х )", после чего просто поместить в найденный элемент последний элемент массива, а потом этот последний элемент грохнуть? Типа:
    Попытка 
        МойМассив[ МойМассив.Найти( Х ) ] = МойМассив[ МойМассив.ВГраница() ];
        МойМассив.Удалить( МойМассив.ВГраница() )
    Исключение КонецПопытки;
Egovigor; Dmitrij-2; gzharkoj; VitaliyCeban; +4 Ответить
4. Def.Gh 29 24.02.21 14:09 Сейчас в теме
(1)
Попытка
МойМассив[ МойМассив.Найти( Х ) ] = МойМассив[ МойМассив.ВГраница() ];
МойМассив.Удалить( МойМассив.ВГраница() )
Исключение КонецПопытки;


Если я правильно понял о чем вы то тогда поменяется порядок элементов в массиве.
10. starik-2005 3033 24.02.21 16:19 Сейчас в теме
(4) а почему нас это должно волновать?
12. Def.Gh 29 24.02.21 18:20 Сейчас в теме
(10)
а почему нас это должно волновать?


задачи разные бывают. бывают такие где это принципиально.
и опять же - попробуйте написать полный код удаления элементов по условию из массива с использованием вашего алгоритма и сделайте замер.
2. tormozit 7138 15.02.21 14:30 Сейчас в теме
Че мелочиться, давайте проверим и другие упорядоченные коллекции. Переставлять там уже дешево не выйдет. Но зависимость длительности от количества элементов было бы интересно сопоставить.
5. Def.Gh 29 24.02.21 14:11 Сейчас в теме
(2)

2. tormozit 6222 15.02.21 14:30
Че мелочиться, давайте проверим и другие упорядоченные коллекции. Переставлять там уже дешево не выйдет. Но зависимость длительности от количества элементов было бы интересно сопоставить


если вам нечем заняться - вперед и с песней.
в статье речь идет о неупорядоченном массиве.
3. t278 56 16.02.21 02:32 Сейчас в теме
Если Условие1(ЭлМассва) Тогда
      МаксимальныйИндекс = МаксимальныйИндекс + 1;
      Массив[МаксимальныйИндекс] = ЭлМассва;                                                
   КонецЕсли;

Здесь затирается элемент?
6. Def.Gh 29 24.02.21 14:13 Сейчас в теме
(3) по сути да. в конце идет обрезание массива до нужной длинны.
7. tormozit 7138 24.02.21 14:49 Сейчас в теме
Проверил смелое предположение автора и получил другой результат - оба метода удаления работают с сопоставимой скоростью. Видимо у автора были неодинаковые условия замеров. Ниже код для консоли кода ИР

КоличествоЭлементов = 10000;
ГенераторСлучайныхЧисел = новый ГенераторСлучайныхЧисел;      
Массив = Новый Массив;          
Для Индекс = 1 По КоличествоЭлементов Цикл                          
    Массив.Добавить(ГенераторСлучайныхЧисел.СлучайноеЧисло(0,200) - 100);                 
КонецЦикла;   

ирОбщий.НачатьЗамерЛкс(, "Замер1");
Для обратныйИндекс = - Массив.ВГраница() По 0 Цикл
   Индекс = - обратныйИндекс;
   Если Истина Тогда
      Массив.Удалить(Индекс);        
   КонецЕсли;
КонецЦикла;
ирОбщий.КончитьЗамерЛкс();

/////////////////////////////////
ГенераторСлучайныхЧисел = новый ГенераторСлучайныхЧисел;      
Массив = Новый Массив;          
Для Индекс = 1 По КоличествоЭлементов Цикл                          
    Массив.Добавить(ГенераторСлучайныхЧисел.СлучайноеЧисло(0,200) - 100);                 
КонецЦикла;   

ирОбщий.НачатьЗамерЛкс(, "Замер2");
МаксимальныйИндекс = -1;
Для Каждого ЭлМассва Из Массив Цикл
   Если Истина Тогда
      МаксимальныйИндекс = МаксимальныйИндекс + 1;
      Массив[МаксимальныйИндекс] = ЭлМассва;                                                
   КонецЕсли;       
КонецЦикла;
Пока Массив.ВГраница() > МаксимальныйИндекс Цикл
   Массив.Удалить(Массив.ВГраница());               
КонецЦикла;
ирОбщий.КончитьЗамерЛкс();
Показать

Он выдает
Окончание замера "Замер1" - Длительность = 0.048с
Окончание замера "Замер2" - Длительность = 0.044с
8. Def.Gh 29 24.02.21 14:53 Сейчас в теме
(7) согласен с вашими выводами для малого количества данных. а теперь попробуйте увеличить количество данных в 1000 раз.
массив из 10000 элементов сложно назвать большим ;)
9. tormozit 7138 24.02.21 14:59 Сейчас в теме
(8) Сделал для 1000 000.
Окончание замера "Замер1" - Длительность = 4.756с
Окончание замера "Замер2" - Длительность = 4.614с
11. Def.Gh 29 24.02.21 18:19 Сейчас в теме
в вашем примере есть существенная ошибка - у вас условие - истина.
поставьте условие больше на ЭлМассва > 0
13. tormozit 7138 24.02.21 19:34 Сейчас в теме
(11) Да. Теперь получил похожую разницу. Признаю, что то интересное в этом есть. Но твой способ может и немного проиграть классическому, если большинство удаляемых элементов будут во второй половине массива. А вот если большинство будет в первой половине, то твой способ сильно выигрывает:
Коэф = 0.5; // [0;1]

КоличествоЭлементов = 100000;
ЗначениеЗаполнения = 0;
Массив = Новый Массив;          
Для Индекс = 1 По КоличествоЭлементов Цикл                          
	Массив.Добавить(ЗначениеЗаполнения);
КонецЦикла;   

ирОбщий.НачатьЗамерЛкс(, "Замер1");
Для обратныйИндекс = - Массив.ВГраница() По 0 Цикл
	Индекс = - обратныйИндекс;
	Если Индекс < КоличествоЭлементов*Коэф Тогда
		Массив.Удалить(Индекс);        
	КонецЕсли;
КонецЦикла;
ирОбщий.КончитьЗамерЛкс();

/////////////////////////////////
Массив = Новый Массив;          
Для Индекс = 1 По КоличествоЭлементов Цикл                          
	Массив.Добавить(ЗначениеЗаполнения);
КонецЦикла;   

ирОбщий.НачатьЗамерЛкс(, "Замер2");
МаксимальныйИндекс = -1;
Индекс = 0;
Для Каждого ЭлМассва Из Массив Цикл
	Если Индекс < КоличествоЭлементов*Коэф Тогда
		МаксимальныйИндекс = МаксимальныйИндекс + 1;
		Массив[МаксимальныйИндекс] = ЭлМассва;                                                
	КонецЕсли;       
	Индекс = Индекс + 1;
КонецЦикла;
Пока Массив.ВГраница() > МаксимальныйИндекс Цикл
	Массив.Удалить(Массив.ВГраница());               
КонецЦикла;
ирОбщий.КончитьЗамерЛкс();
Показать

выдает
Окончание замера "Замер1" - Длительность = 1.572с
Окончание замера "Замер2" - Длительность = 0.617с

А если увеличить размер массива в 10 раз, то разница тоже увеличивается в 10 раз:
Окончание замера "Замер1" - Длительность = 116с
Окончание замера "Замер2" - Длительность = 6с
14. Def.Gh 29 24.02.21 22:00 Сейчас в теме
(13) об чем собственно и речь. и опять же у тебя не совсем честное условие - тут будет лучше именно удалять по значению, когда мы не знаем где какое значение.
метод имеет право на жизнь, но именно когда надо сохранить порядок и данных много.
почему не рассматривал вариант создания нового массива - отвечу сразу - ОЗУ не резиновое =)
Оставьте свое сообщение