Удаление строк в таблице значений

1. Metabos 29 31.01.18 21:50 Сейчас в теме
Добрый вечер. Подскажите, что нужно сделать, чтобы удаление в таблице значений было корректным? Я методом Найти ищу сроку. Ее удаляю, но после первого удаления строки, строки меняются как то и удаляются или не все или не те.
По теме из базы знаний
Найденные решения
6. protexprotex 139 31.01.18 22:25 Сейчас в теме
(1) Добрый день. Удалять надо так:

Сч = 0;
Пока (Сч < ТаблицаДанных.Количество ()) Цикл
Строка = ТаблицаДанных.ПолучитьСтроку (Сч);
Если (УдаляемСтроку (Строка)) Тогда
ТаблицаДанных.Удалить(Сч);
Иначе
Сч = Сч + 1;
КонецЕсли;
КонецЦикла;

где Функция УдаляемСтроку () - анализ строки на удаление. Работает правильно и быстро.
user1925481; VyacheslavShilov; user915901; asupigor; kabantus; hasp_x; Алсушка80; user665211_antonfo; user981405; dimisa; RolexStrider; Merkalov; jaroslav.h; MaxTolya; rmIvanT; +15 Ответить
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
3. Xershi 1547 31.01.18 22:09 Сейчас в теме
(1) обходить таблицу надо с конца. А вы похоже с начала, вот индекс теряется!
kild; YanTsys; +2 Ответить
5. kild 91 31.01.18 22:23 Сейчас в теме
(3) Можно и не обходить. Автор-то не приводит свой код и не ясно что ему нужно. Лишь что-то ищет функцией Найти и удаляет. В этом случае обход может и не понадобится.

Вот куча способов удаление.

// 1. Удаление строк согласно условию
      

    НулевыеСтроки = ТаблицаПослеПодмен.НайтиСтроки(Новый Структура("Сумма",0));
      

    Для каждого СтрокаТаблицы Из НулевыеСтроки Цикл
      

    	ТаблицаПослеПодмен.Удалить(СтрокаТаблицы)
      

    КонецЦикла;
      

    
      

    // Нужно оставить строки только соответствующие условию,а остальные удалить то:
      

    ПараметрыОтбора = Новый Структура("Цена",15000);
      

    ТЗНов = ТЗ.Скопировать(ПараметрыОтбора); 
      

    // в результате в ТЗнов будут только строки из ТЗ, в которых значение поля Цена = 15000
      

    
      

    // 2. Удаление определенной строки, например УдаляемаяСтрока = 5;
      

    ТаблицаЗначений.Удалить(УдаляемаяСтрока); 
      

    
      

    // 3. Удаление первой строки
      

    ТаблицаЗначений.Удалить(0); 
      

    
      

    // 4. Удаление определенной колонки, например УдаляемаяКолонка = 3;
      

    ТаблицаЗначений.Колонки.Удалить(УдаляемаяКолонка); 
      

    
      

    // 5. Удалить первую колонку
      

    ТаблицаЗначений.Колонки.Удалить(0); 
      

    
      

    // 6. Удаление строк перебором, проверяя условие
      

    СтаршийИндексКолонок = ТаблицаЗначений.Колонки.Количество() - 1; 
      

    Индекс = ТаблицаЗначений.Количество() - 1; 
      

    Пока Индекс > = 0 Цикл 
      

    	Для Сч = 0 По СтаршийИндексКолонок Цикл 
      

    		Если ТипЗнч(ТаблицаЗначений[Индекс][Сч]) = Тип("Число") Тогда 
      

    			ТаблицаЗначений.Удалить(Индекс); 
      

    			Прервать; 
      

    		КонецЕсли; 
      

    	КонецЦикла; 
      

    	Индекс = Индекс - 1; 
      

    КонецЦикла;
      
Показать
starovton; user1621493; AlexGoldT; marinelle; HIVvich; Tworozhok; craftytigra; Simonov_NPM; +8 Ответить
8. YanTsys 12 31.01.18 22:28 Сейчас в теме
(5) Вообще-то проблема сформулирована крайне чётко, перечитайте вопрос... :)
7. пользователь 31.01.18 22:27
Сообщение было скрыто модератором.
...
6. protexprotex 139 31.01.18 22:25 Сейчас в теме
(1) Добрый день. Удалять надо так:

Сч = 0;
Пока (Сч < ТаблицаДанных.Количество ()) Цикл
Строка = ТаблицаДанных.ПолучитьСтроку (Сч);
Если (УдаляемСтроку (Строка)) Тогда
ТаблицаДанных.Удалить(Сч);
Иначе
Сч = Сч + 1;
КонецЕсли;
КонецЦикла;

где Функция УдаляемСтроку () - анализ строки на удаление. Работает правильно и быстро.
user1925481; VyacheslavShilov; user915901; asupigor; kabantus; hasp_x; Алсушка80; user665211_antonfo; user981405; dimisa; RolexStrider; Merkalov; jaroslav.h; MaxTolya; rmIvanT; +15 Ответить
10. YanTsys 12 31.01.18 22:32 Сейчас в теме
(6) Я всё таки предпочитаю удалять строки после полной обработки таблицы, и индексы не портятся и не нужно помнить нюансы каждого языка программирования :)
12. protexprotex 139 31.01.18 22:39 Сейчас в теме
(10) Ну, тогда можете так:
ТаблицаДанных.Колонки.Добавить ("Удалить");
Для Каждого ТекСтрока Из ТаблицаДанных Цикл
    ТекСтрока.Удалить = УдаляемСтроку (Строка);
КонецЦикла;
ОтборСтрок = Новый Структура ("Удалить", Истина);
Строки = ТаблицаДанных.НайтиСтроки (ОтборСтрок );
ТаблицаДанных.Колонки.Удалить("Удалить");

И теперь удаляйте строки в ТаблицаДанных из списка строк Строки

Хотя, это уже изврат если просто нужно удалить строки по какому - то простому условия. Этот алгоритм имеет смысл только если удаление строки зависит от данных в других строках. Тогда да.
lolovlol1; klaus38; user665211_antonfo; +3 Ответить
19. YanTsys 12 01.02.18 08:23 Сейчас в теме
(12) А чем не понравился мой вариант (4) с хранением строк которые потом нужно удалить в отдельном массиве? Тем более что если речь идет о таблицах которые динамически отражаются на экране то добавление лишней колонки отнимет лишнее время :)
21. Metabos 29 01.02.18 10:21 Сейчас в теме
(19)
А чем не понравился мой вариант (4) с хранением строк которые потом нужно удалить в отдельном массиве? Тем более что если речь идет о таблицах которые динамически отражаются на экране то добавление лишней колонки отнимет лишнее время :)

:-)) Я понимаю, что причина в номерах строки, что сбивается. И в решении было видно, что работа идет с этим. А в вашем решении как будто 2 раза одно и тоже по циклу проходит. Код не только должен работать, но и быть понятным, мне просто другой вариант был чисто визуально понятнее. Может он по другим параметрам уступает, но тут это не так важно, этот объект пользователи используют самое частое раз в день. А по факту за прошлый год раз 10. Строк там мало, 5-6. Поэтому не так важно, сколько он будет отрабатывать.
26. protexprotex 139 01.02.18 12:17 Сейчас в теме
(19) Ну, это уже кому как нравиться. Приносить в жертву понятность и легкость восприятия программного кода в угоду лишней миллисекунде выполнения кода - я думаю, что не стоит. Если бы тут был объем данных, скажем, строк миллиард, то да. Я бы тогда написал уже код или с индексами, или методы статистического анализа применил. Или метод золотого сечения и пр. А тут задача локальная. Мне кажется, что не стоит.
user665211_antonfo; +1 Ответить
13. Metabos 29 31.01.18 22:48 Сейчас в теме
(6) Строка = ТаблицаДанных.ПолучитьСтроку (Сч); - только не получитьстроку, а получить.
Да, работает спасибо!
15. protexprotex 139 31.01.18 23:10 Сейчас в теме
(13) Ну да, конечно получить.
16. kild 91 31.01.18 23:11 Сейчас в теме
(6) У вас похоже самый медленный алгоритм удаление из всех представленных. В каждой итерации вычисляется количество строк всей таблицы ТаблицаДанных.Количество () и доп.условия. Чтобы этого не было нужно перебирать с конца, как говорили остальные комментаторы.
Самый быстрый и легкий путь:

	 Индекс = ТаблицаЗначений.Количество() - 1; 
	 Пока Индекс >= 0 Цикл   		
	     Если УсловиеДляУдаленияСтроки(ТаблицаЗначений[Индекс]) Тогда      
	    	 ТаблицаЗначений.Удалить(Индекс);                              
	     КонецЕсли;         			
	     Индекс = Индекс - 1;                                                                         
	 КонецЦикла;
Показать


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

	Количество = ТаблицаДанных.Количество();
	Сч = 0; 
	Пока (Сч < Количество) Цикл 
				
		Если (УдаляемСтроку(ТаблицаДанных[Сч])) Тогда 
			ТаблицаДанных.Удалить(Сч); 
			Количество = ТаблицаДанных.Количество();
			Продолжить; 			
		КонецЕсли; 
		
		Сч = Сч + 1;
		
	КонецЦикла;
Показать
Sottoz; maxim_saharov; +2 Ответить
18. protexprotex 139 31.01.18 23:17 Сейчас в теме
(16) Вообще - то количество строк вычисляется компилятором не при каждом обращении к функции КоличестроСтрок(), а просто возвращается из предвычисленного параметра. Т.к. КоличествоСтрок() - это просто функция которая возвращает свойство таблицы КоличествоСтрок. При удалении строки из этого свойства вычитается 1-ца, а при добавлении строки добавляется единица. Так что Вы тут не правы. Это аналог TList -
TList *List = new TList;
for (int i = 0; i < 10; i++)
{
List-Add((void *)(new float[10]));
}
и здесь при обращении int Num = List->Count - также не вычисляется кол-во элементов в списке List, - он просто храниться в свойстве потомка класса.
user665211_antonfo; +1 Ответить
24. spacecraft 01.02.18 11:31 Сейчас в теме
(18) для небольших данных разница будет не существенна. На больших уже заметна.
Вот тест:
&НаКлиенте
Процедура Тест1(Команда)
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сч = 0;
	Пока (Сч < ТЗРезультат.Количество()) Цикл
		Сч = Сч + 1;
	КонецЦикла;
	ВремяОкончания = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сообщить("Время выполнения: "+(ВремяОкончания - ВремяНачала));
КонецПроцедуры

&НаКлиенте
Процедура Тест2(Команда)
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сч = 0;
	Пока (Сч < КоличествоСтрокТЗ) Цикл
		Сч = Сч + 1;
	КонецЦикла;
	ВремяОкончания = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сообщить("Время выполнения: "+(ВремяОкончания - ВремяНачала));
КонецПроцедуры
Показать

Для КоличествоСтрокТЗ = 1 000 000
Тест1: "Время выполнения: 7 128"
Тест2: "Время выполнения: 6 781"
27. protexprotex 139 01.02.18 12:20 Сейчас в теме
(24) Ну, во первых тут у Вас время в миллисекундах, и 200 миллисекунд разница. Для чистоты эксперимента надо прогнать алгоритм раз 100 и усреднить. Т.к. при запуске алгоритмов включается такие процессы, как использование кеша процессора/запуск других служб винды и пр. Тут судить нельзя по одному тесту. А во вторых:
Ну, это уже кому как нравиться. Приносить в жертву понятность и легкость восприятия программного кода в угоду лишней миллисекунде выполнения кода - я думаю, что не стоит. Если бы тут был объем данных, скажем, строк миллиард, то да. Я бы тогда написал уже код или с индексами, или методы статистического анализа применил. Или метод золотого сечения и пр. А тут задача локальная. Мне кажется, что не стоит.
user665211_antonfo; +1 Ответить
25. spacecraft 01.02.18 11:44 Сейчас в теме
(18) А вот когда в ТЗ меняются строки, то становится совсем интересно:
&НаКлиенте
Процедура Тест1(Команда)
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сч = 0;
	Пока (Сч < ТЗРезультат.Количество()) Цикл
		Если Сч%2 = 0 Тогда
			ТЗРезультат.Удалить(Сч);
		КонецЕсли;
		Сч = Сч + 1;
	КонецЦикла;
	ВремяОкончания = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сообщить("Тест1: Время выполнения: "+(ВремяОкончания - ВремяНачала));
КонецПроцедуры

&НаКлиенте
Процедура Тест2(Команда)
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сч = 0;
	Пока (Сч < КоличествоСтрокТЗ/2) Цикл
		Если Сч%2 = 0 Тогда
			ТЗРезультат.Удалить(Сч);
		КонецЕсли;
		Сч = Сч + 1;
	КонецЦикла;
	ВремяОкончания = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сообщить("Тест2: Время выполнения: "+(ВремяОкончания - ВремяНачала));
КонецПроцедуры
Показать

Для КоличествоСтрокТЗ = 100 000
Тест1: Время выполнения: 26 286
Тест2: Время выполнения: 20 127

Более 6 секунд на 100 000 строках. Половина из которых удаляется.
Вот это уже затратно.
28. protexprotex 139 01.02.18 12:25 Сейчас в теме
(25) Хм. Я даже не знаю как это комментировать. Неужели не понятно, что при удалении строки будет пересчет количества строк. И вот в этом алгоритме -
Пока (Сч < ТЗРезультат.Количество()) Цикл
        Если Сч%2 = 0 Тогда
            ТЗРезультат.Удалить(Сч);
        КонецЕсли;
        Сч = Сч + 1;
    КонецЦикла;

будет увеличение времени на пересчет.
А при удалении строк в алгоритме
Пока (Сч < КоличествоСтрокТЗ/2) Цикл
        Если Сч%2 = 0 Тогда
            ТЗРезультат.Удалить(Сч);
        КонецЕсли;
        Сч = Сч + 1;
    КонецЦикла;

пересчет количества строк не будет - у Вас в переменной хранится (и процессор деление на два заменить на битовый сдвиг) - вы же не знаете сколько строк будет удалено. А тут у Вас известно - ровно половина. Этот алгоритм попахивает нечистотой эксперимента.
29. spacecraft 01.02.18 12:34 Сейчас в теме
(28)
Я даже не знаю как это комментировать. Неужели не понятно, что при удалении строки будет пересчет количества строк.

ок. смотрим (18):
Вообще - то количество строк вычисляется компилятором не при каждом обращении к функции КоличестроСтрок(), а просто возвращается из предвычисленного параметра. Т.к. КоличествоСтрок() - это просто функция которая возвращает свойство таблицы КоличествоСтрок. При удалении строки из этого свойства вычитается 1-ца, а при добавлении строки добавляется единица

Комментировать и правда нечего. Все и так понятно.
30. protexprotex 139 01.02.18 12:51 Сейчас в теме
(29) Если Вы удаляете из таблицы строку, то из переменной ответственной за хранение кол-ва строк в таблице вычитается 1-ца. Это не относится к тому, что каждый раз при обращении к функции Количество() таблицы значений программа будет каждый раз пробегаться по строкам таблицы и подсчитывать их количество - так никто не делает при разработке компилятора транслятора - делают через хранение кол-ва строк в отдельной переменной - свойстве класса. Это же элементарно :-)
32. spacecraft 01.02.18 12:55 Сейчас в теме
(30) действительно не понимаете о чем речь, или специально в другую сторону уводите?
Удаление строк одинаково в обоих случаях. Тест1 и Тест2.
Если не удалять строки, то разница во времени выполнения не принципиальная. Логично, вычисление ТЗ.Количество() просто кешируется.
Если происходит удаление, то Количество() каждый раз выполняется. И разница во времени становится уже очень заметна.
Так что не надо говорить, что с условием ТЗ.Количество() не будет разницы. Вот о чем речь.
native-api; Capitullo; +2 Ответить
31. protexprotex 139 01.02.18 12:53 Сейчас в теме
(29) А у Вас метод такой - Вы задаете программе сколько надо удалить строк, и начинаете это количество строк удалять. Вопрос - откуда Вы знаете сколько строк надо удалить?
как у Вас:
Пока (Сч < КоличествоСтрокТЗ/2) Цикл
Если Сч%2 = 0 Тогда
ТЗРезультат.Удалить(Сч);
КонецЕсли;
Сч = Сч + 1;
КонецЦикла;

тут Вы откуда то еще до анализа таблицы уже знаете, что надо удалить половину строк таблицы.
33. spacecraft 01.02.18 12:56 Сейчас в теме
(31) смотрите алгоритм. В обоих Тест1 и Тест2 удаляются четные элементы. Это ровно половина выборки.
34. protexprotex 139 01.02.18 13:10 Сейчас в теме
(33) Ну а причем тут четные элементы выборки? - прочитайте постановку задачи у автора - ему надо удалить не четные элемент выборки, а анализировать строку на необходимость удаления. Зачем Вы делаете искусственные предположения, когда задача ясна из постановки?
35. spacecraft 01.02.18 13:34 Сейчас в теме
(34) мы не обсуждаем сейчас алгоритм автора топика. Мы обсуждаем утверждение, что:
Вообще - то количество строк вычисляется компилятором не при каждом обращении к функции КоличестроСтрок(), а просто возвращается из предвычисленного параметра. Т.к. КоличествоСтрок() - это просто функция которая возвращает свойство таблицы КоличествоСтрок. При удалении строки из этого свойства вычитается 1-ца, а при добавлении строки добавляется единица.

и второе противоречащее утверждение:
Я даже не знаю как это комментировать. Неужели не понятно, что при удалении строки будет пересчет количества строк.

Я привел абстрактный Тест проверки этих утверждений. Оба теста выполняют одинаковую работу. У обоих одинаковая итерация.
Capitullo; +1 Ответить
36. protexprotex 139 01.02.18 13:45 Сейчас в теме
(35) Ну, тогда таких искусственных алгоритмов можно много придумать которые будут быстрее работы некоторого алгоритма но уже в реальных данных. Ценность таких алгоритмов в чем? - просто доказать? - ну хорошо, Вы мне доказали. И?
38. spacecraft 01.02.18 13:52 Сейчас в теме
(36) ок. Вот еще тест:
&НаКлиенте
Процедура Тест3(Команда)
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сч = 0;
	Пока (Сч < ТЗРезультат.Количество()) Цикл
		Если Сч < 1000 Тогда
			ТЗРезультат.Удалить(Сч);
		Иначе 
			Прервать;
		КонецЕсли;
		Сч = Сч + 1;
	КонецЦикла;
	ВремяОкончания = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Сообщить("Тест3: Время выполнения: "+(ВремяОкончания - ВремяНачала));

КонецПроцедуры
Показать

Объясню алгоритм. Не важно сколько элементов в ТЗ. Всегда будут выполняться только проход и удаление первых 1000 элементов.
И вот итог:
Кол-во элементов в ТЗ | Время мсек
10 000 | 99
100 000 | 997
1 000 000 | 15 532

Показательно. Каждый раз именно рассчитывается количество элементов.
40. protexprotex 139 01.02.18 14:02 Сейчас в теме
(38) Нет, неправильно. При удалении строки производится перераспределение памяти. Если таблица большая, то и времени на перераспределение памяти больше. Это не относится к расчету кол-ва строк.
Аналог TList в c++ builder. Кстати, в предыдущих Ваших алгоритмах - тоже такая ситуация может быть. Т.к. все зависит от заполненности "кучи" памяти. И для чистоты эксперимента надо прогнать алгоритм раз 50 и потом усреднить.
41. spacecraft 01.02.18 14:13 Сейчас в теме
(40) как это соотносится с:
Т.к. КоличествоСтрок() - это просто функция которая возвращает свойство таблицы КоличествоСтрок. При удалении строки из этого свойства вычитается 1-ца, а при добавлении строки добавляется единица.

Предыдущие тесты (Тест1 и Тест2) оба удаляют строку. Временные затраты на это одинаковые.

Не надо притягивать алгоритмы с++ builder на работу 1С кода.
43. protexprotex 139 01.02.18 14:18 Сейчас в теме
(41) Относится просто - когда Вы удаляете строку из таблицы с кол-вом строк в 1000 - это одно, а когда из таблицы с кол-вом строк в 1000000 - это другое. Накладные расходы на перераспределение памяти в таблицах с разным кол-вом строк - разное. А по поводу c+++ builder - это я Вам пример привел просто для понимания - т.к. ТаблицаЗначений в 1С - это STL - контейнер. А TList в c++ builder - это динамический список очень похожий на STL - контейнер.
46. spacecraft 01.02.18 14:35 Сейчас в теме
(43) очередная попытка притянуть функциональность c++ builder к 1С.
В каком месте мы вызываем delete объекту? Согласно с++ объекты созданные в куче без явного удаления не уничтожаются.
Где мы выделяем память новому объекту?

Не стоит лезть во внутреннее строение платформы, не зная его механизмов.
48. protexprotex 139 01.02.18 14:40 Сейчас в теме
(46) delete вызывается неявно. Иначе бы при удалении строк/таблицы была бы утечка памяти. Это, я думал, все знают и не стал это писать.
То что Вы пишите - "Согласно с++ объекты созданные в куче без явного удаления не ничтожаются." - т.е. Вы хотите сказать, что когда я:
Табл = Новый ТаблицаЗначений
и потом
Табл = НеОпределено
память выделенная под Табл не возвращается операционке?
тогда сделайте миллиард Табл = Новый ТаблицаЗначений и также миллиард Табл = НеОпределено и посмотрите сколько памяти у Вас осталось. Уверяю - столько же.
"Где мы выделяем память новому объекту? " - когда делаете Новый (аналог new c++) - это и есть выделение памяти под новый объект.
49. spacecraft 01.02.18 14:42 Сейчас в теме
(48) ок. Скажу прямо: "сборка мусора" ничего не говорит?
52. protexprotex 139 01.02.18 14:47 Сейчас в теме
(49) Сборка мусора - это когда программа закрывается и планировщик вычищает не возвращенную память.
54. spacecraft 01.02.18 14:49 Сейчас в теме
(52) вот блин. Все программы на java и c# мертворожденные. Не успели загрузиться и уже выгружаются.
Дальше нечего обсуждать...
56. herfis 513 01.02.18 14:57 Сейчас в теме
(52) Ну, примерно в той же степени, как и ядерную атаку можно назвать сборкой мусора - мусор сгорит тоже :)
(53) Я терпел. Оскорблений больше не будет. Не вижу смысла продлжать разговор.
50. spacecraft 01.02.18 14:43 Сейчас в теме
(48)
Вы хотите сказать, что когда я:
Табл = Новый ТаблицаЗначений
и потом
Табл = НеОпределено
память выделенная под Табл не возвращается операционке?

Если вот это дословно перевести на c++, то да. Будет явная утечка памяти.
Потому и говорю, не надо прямую ассоциацию приводить с с++
42. herfis 513 01.02.18 14:16 Сейчас в теме
(40) Какое еще перераспределение памяти в связанных списках?
44. protexprotex 139 01.02.18 14:21 Сейчас в теме
(42) Перераспределение памяти при удалении строки, а не перераспределении в списке. Т.к. память высвобождается и отдается операционке для использования другими процессорами - иначе была бы утечка памяти (хотя, этого добра хватает в 1С :-) ). Или Вы думаете что это бесплатная операция? - и на нее не тратится тактов процессора?
45. herfis 513 01.02.18 14:27 Сейчас в теме
(44) Оставим спорный момент возврата памяти операционке (по каждому чиху этого не делают и уж в одинэсной ТЗ - точно). Каким образом накладные расходы на удаление одной строки зависят от размера таблицы?
47. protexprotex 139 01.02.18 14:36 Сейчас в теме
(45) Зависят очень просто - чем больше сама таблица - тем больше она занимает страниц памяти. При удалении строк которые находятся в разных дампах(страницах) памяти процу приходится активно переключаться между дампами (страницами). Если таблица маленькая, и она убирается в одну страницу, то работа происходит в контексте одной страницы. Это если организована постраничная адресация. Если используется плоская модель памяти - то тут, возможно (надо посмотреть) и не будет увеличения времени удаления. + ко всему прочему надо учитывать объем кеша проца и какой объем данных закеширован.
51. herfis 513 01.02.18 14:45 Сейчас в теме
(47) Еще раз - в (43) было заявлено, что удаление ОДНОЙ строки в таблице бОльшего размера займет больше времени.
И теперь пытаетесь подвести под это утверждение что? Что одна строка в большой таблице будет занимать несколько страниц памяти? И при каждом удалении строки будет осуществляться возврат памяти операционке? Признайтесь, что ошиблись и перестаньте нести бред.
Насчет возврата памяти операционке - ознакомьтесь со значением слова "куча", которое вы тут употребляли и как она работает.
53. protexprotex 139 01.02.18 14:49 Сейчас в теме
(51) Ну не надо кидаться словами "бред". Строка может занимать память между двумя страницами - в конце одной и в начале другой. Давайте без оскорблений.
55. spacecraft 01.02.18 14:56 Сейчас в теме
(53) даже с++ не работает с ячейками памяти напрямую (если только специально взламывать). Она работает с виртуальным адресным пространством, которое ему выделяет ОС.
В итоге много терминов без понимания их сути.
62. Cool_vsi 24.11.21 11:08 Сейчас в теме
(6) для старый платформ вместо Строка = ТаблицаДанных.ПолучитьСтроку (Сч); пишем Строка = ТаблицаДанных.Получить (Сч);

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

и спс за это решение!
63. kabantus 14.03.23 14:17 Сейчас в теме
(6)
Строка = ТаблицаДанных.ПолучитьСтроку (Сч);

Без опечатки: Строка = ТаблицаДанных.Получить (Сч);
2. kild 91 31.01.18 21:59 Сейчас в теме
(1) Кусок кода выложите как у вас удаление реализовано из тз
9. Metabos 29 31.01.18 22:32 Сейчас в теме
(2)
Для каждого Строка из ТЗ Цикл 
		НайденнаяСтрока = Список.Найти(Строка.Колонка, "Колонка"); 
		Если НайденнаяСтрока = Неопределено Тогда 
			ТЗ.Удалить(Строка);
		КонецЕсли;
	КонецЦикла;
11. YanTsys 12 31.01.18 22:35 Сейчас в теме
(9)
УдаляемыеСтроки=новый массив;
Для каждого Строка из ТЗ Цикл 
	НайденнаяСтрока = Список.Найти(Строка.Колонка, "Колонка"); 
	Если НайденнаяСтрока = Неопределено Тогда 
              УдаляемыеСтроки.Добавить(Строка);
	КонецЕсли;
КонецЦикла;
Для Каждого УдаляемаяСтрока из УдаляемыеСтроки Цикл
 ТЗ.Удалить(УдаляемаяСтрока);
КонецЦикла;
Показать
4. YanTsys 12 31.01.18 22:17 Сейчас в теме
Самый простой вариант:

УдаляемыеСтроки=новый массив;
Для Каждого СтрокаТЗ из ТЗ Цикл
 Если СтрокаТЗ.Сумма<0 Тогда
  УдаляемыеСтроки.Добавить(СтрокаТЗ);
 КонецЕсли;
КонецЦикла;
Для Каждого УдаляемаяСтрока из УдаляемыеСтроки Цикл
 ТЗ.Удалить(УдаляемаяСтрока);
КонецЦикла;
Показать
HIVvich; klaus38; slitov; PowerBoy; KoC_one; ru_spaiky; pisanko; zba; herfis; +9 Ответить
37. herfis 513 01.02.18 13:51 Сейчас в теме
(4) Тоже всегда делаю именно так. Это самый наглядный и легко читаемый вариант из всех.
KoC_one; YanTsys; +2 Ответить
14. Metabos 29 31.01.18 22:49 Сейчас в теме
Спасибо всем. Нашла решение, которое показалось самым простым.
17. kild 91 31.01.18 23:13 Сейчас в теме
(14) Вот самый быстрый и просто способ из всех:

	 Индекс = ТаблицаЗначений.Количество() - 1; 
	 Пока Индекс >= 0 Цикл   		
	     Если УсловиеДляУдаленияСтроки(ТаблицаЗначений[Индекс]) Тогда      
	    	 ТаблицаЗначений.Удалить(Индекс);                              
	     КонецЕсли;         			
	     Индекс = Индекс - 1;                                                                         
	 КонецЦикла;
Показать
Xershi; YanTsys; +2 Ответить
20. Xershi 1547 01.02.18 09:38 Сейчас в теме
(17) одно из решений ответа из (3)!
22. Metabos 29 01.02.18 10:22 Сейчас в теме
(20) А почему с конца не будет такого?
23. Xershi 1547 01.02.18 10:39 Сейчас в теме
(22) ответ на ваш вопрос дан в (3).
59. ildarovich 7926 01.02.18 16:15 Сейчас в теме
(17) Этот способ только на первый взгляд самый быстрый. Во-первых, его можно записать короче:
   Для Индекс = - РабочаяТаблица.Количество() + 1 По 0 Цикл
		Если РабочаяТаблица[- Индекс][0] = 0 Тогда // условие удаления
			РабочаяТаблица.Удалить(- Индекс)
		КонецЕсли
	КонецЦикла
Во-вторых, даже в таком виде он выполняется примерно столько-же, сколько (7). Метод в (7) экономит на времени итерации переменной цикла, которая оказывается не нужна, когда элемент удален.
Но оба они (7) и (16) сильно проигрывают (примерно в два раза) методу с предварительным отбором списка удаляемых строк через НайтиСтроки() как в (5).
native-api; +1 Ответить
60. herfis 513 01.02.18 16:41 Сейчас в теме
(59)
Но оба они (7) и (16) сильно проигрывают (примерно в два раза) методу с предварительным отбором списка удаляемых строк через НайтиСтроки() как в (5).

А за счет чего такой сильный проигрыш? Доступ по индексу такой медленный?
66. native-api 28.08.24 11:31 Сейчас в теме
(60) Полагаю, потому, что в "НайтиСтроки()" итерация ведется средствами С++, без накладных расходов интерпретатора языка 1С.

"НайтиСтроки()", однако, умеет проверять только точное совпадение с константой, и не подходит, если условие другое.
39. herfis 513 01.02.18 13:54 Сейчас в теме
Если кого-то из академического интереса интересует "самый быстрый" способ, то даже конкурсы проходили - можно найти готовые обработки со сравнительным тестированием различных способов.
57. МихаилМ 01.02.18 15:09 Сейчас в теме
+(39)
на хиппо для 7.7 был первый конкурс на самое быстрое удаление строк из ТЗ с призами году в 2002. потом на мисте был конкурс для 8.1. не увидел метода копирования ТЗ с отбором обратным условием.
ildarovich; +1 Ответить
58. ildarovich 7926 01.02.18 15:29 Сейчас в теме
(57) Этот метод (копирования) самый быстрый, примерно в 10 раз быстрее на миллионе строк:
РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("Колонка1", 1))
Здесь удаляются строки с нулями, оставляются с единицей в Колонке1.
marinelle; Simonov_NPM; +2 Ответить
61. iCortezik 8 04.03.20 07:57 Сейчас в теме
Пока ТаблицаДанных.НайтиСтроки(Новый структура("Сумма", 0)).Количество() > 0 Цикл
	ТаблицаДанных.Удалить(ГруппыНоменклатуры.НайтиСтроки(Новый структура("Сумма", 0))[0]);	
КонецЦикла;


Хоть и поздно, но сейчас тоже гуглил эту проблему, попробовал лучший ответ, не вышло, но нашел свой вариант
kabantus; +1 Ответить
64. Xershi 1547 19.09.23 17:25 Сейчас в теме
Когда строк для удаления мало оптимально такой код.
Мы не гоняем данные в памяти, а просто перебираем.
Как говорится под каждую задачу, свое решение!
	
	Для Каждого Строка Из ОбъектыОшибок Цикл
		
		Если Строка.Ключ = "2" И ТипЗнч(Строка.Объект) = Тип("ДокументСсылка.УстановкаЦенНоменклатуры") Тогда
			
			ТекущийОбъект = Строка.Объект.ПолучитьОбъект();
			
			Если ТекущийОбъект <> Неопределено Тогда
				
				НужноЗаписать = Ложь;
				
				Товары = ТекущийОбъект.Товары;				
				
				КоличествоСтрок = Товары.Количество();
				
				ТекущийИндекс = КоличествоСтрок - 1;
				
				Пока ТекущийИндекс >= 0 Цикл
					
					СтрокаТовары = Товары.Получить(ТекущийИндекс);
					
					Если СтрокаТовары.Номенклатура.ЭтоГруппа Тогда
						
						Товары.Удалить(СтрокаТовары);
						
						НужноЗаписать = Истина;
						
					КонецЕсли;
					
					ТекущийИндекс = ТекущийИндекс - 1;
										
				КонецЦикла;
				
				Если НужноЗаписать Тогда
				
					ТекущийОбъект.Записать();
					
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЕсли;	
		
	КонецЦикла;
Показать

В УПП умудрились папку впихнуть в документ.
65. пользователь 19.09.23 18:29
Сообщение было скрыто модератором.
...
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот