Самый эффективный способ удалить элементы в массиве

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Самый эффективный способ удалить элементы в массиве

Сообщение ZW » 04.09.2006 20:38:40

Есть запись в которой присутствует динамический массив, периодически необходимо из массива выносить элементы по какомуто критерию. Возникает вопрос каким наиболее эффективным способом это сделать?
У кого нибудь есть идеи?
ZW
новенький
 
Сообщения: 26
Зарегистрирован: 16.08.2006 15:11:23

Сообщение debi12345 » 04.09.2006 21:27:20

Посмотрите в MSEgui, файл "msedatalist.pas". Автор - жутко ненавидит "variants", все тестирует на размер и скорость, поэтому "там" - для простых типов. Думаю, Ваш случай.

Код по части удаления выглядит примерно так:

--------------

procedure deleteitem(var dest: stringarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
dest[index]:= '';
move(dest[index+1],dest[index],sizeof(pointer)*(high(dest)-index));
pointer(dest[high(dest)]):= nil;
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: msestringarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
dest[index]:= '';
move(dest[index+1],dest[index],sizeof(pointer)*(high(dest)-index));
pointer(dest[high(dest)]):= nil;
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: integerarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(integer)*(high(dest)-index));
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: realarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(real)*(high(dest)-index));
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: pointerarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(integer)*(high(dest)-index));
setlength(dest,high(dest));
end;

Примечания :

1) *arty - динамические массивы
2) msestring = widestring
3) для корректировки освободившего места используется сверх-быстрая низкоуровневая "move".

------------

А Ваш "критерий отсева" прямо напрашивается на дополнительный callback-параметр = адрес функции-компаратора, к вышеприведенным процедурам.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение ZW » 06.09.2006 23:00:05

Спасибо за информацию. Но неполучается.
У меня такая структура данных:
p[j].x[y]
То есть p : array of x;

Убирать надо элемент x (то есть массив) из p[j]
Исходная процедура такая:
procedure deleteitem(var dest: integerarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(integer)*(high(dest)-index));
setlength(dest,high(dest));
end;

Но при компиляции возникает ругань на строку setlength(dest,high(dest));
на несовместимость типов.
ZW
новенький
 
Сообщения: 26
Зарегистрирован: 16.08.2006 15:11:23

Сообщение debi12345 » 07.09.2006 10:41:17

ZW писал(а):Спасибо за информацию. Но неполучается.
У меня такая структура данных:
p[j].x[y]
То есть p : array of x;

Убирать надо элемент x (то есть массив) из p[j]
Исходная процедура такая:
procedure deleteitem(var dest: integerarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(integer)*(high(dest)-index));
setlength(dest,high(dest));
end;

Но при компиляции возникает ругань на строку setlength(dest,high(dest));
на несовместимость типов.


А если перевести на массив указателей : array of ^x ?

"Там" есть такая же процедура для указателей. Хотя и возня с динамической памятью, но обычно так и делается.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение ZW » 07.09.2006 15:40:54

debi12345 писал(а):
А если перевести на массив указателей : array of ^x ?

"Там" есть такая же процедура для указателей. Хотя и возня с динамической памятью, но обычно так и делается.


А как перевести и как с ним работать?
ZW
новенький
 
Сообщения: 26
Зарегистрирован: 16.08.2006 15:11:23

Сообщение SergKam » 07.09.2006 16:08:23

а может компилятор не понимает что такое integerarty; ?
SergKam
постоялец
 
Сообщения: 251
Зарегистрирован: 16.11.2005 21:31:11
Откуда: Украина,Харьков

Сообщение ZW » 07.09.2006 17:21:41

SergKam писал(а):а может компилятор не понимает что такое integerarty; ?


Нет, я ему вместо integerarty прописал array of integer
ZW
новенький
 
Сообщения: 26
Зарегистрирован: 16.08.2006 15:11:23

Сообщение debi12345 » 07.09.2006 21:23:17

Нет, я ему вместо integerarty прописал array of integer


А зря. Есть в FPC такой баг-перестраховка на Var-аргументах :

--------------
proc ( var arg: array of integer; ..)
begin
..
setlength(arg, value)
..
end;
-------------

будет ругаться, зато :

----------------
type

integerarty = array of integer;

var
..

proc ( var arg: integerarty; ..)
begin
..
setlength(arg, value)
..
end;
-------------

работает на "ура" :)


Я тоже не сразу понял, почему автор MSEgui всегда объявляет новый тип для открытых массивов.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение ZW » 08.09.2006 00:50:48

debi12345 писал(а):
Нет, я ему вместо integerarty прописал array of integer


А зря. Есть в FPC такой баг-перестраховка на Var-аргументах :

------------------

работает на "ура" :)


Я тоже не сразу понял, почему автор MSEgui всегда объявляет новый тип для открытых массивов.


Мда... до этого я бы фиг додумался:)
Но каким образом считать память, что бы вынести элемент из двумерного массива?
Вернее из записи p[j].x[y]
То есть p : array of x;
можно ли рассматривать таким образом: если high(x)=5, то длина записи p[j] 6*integer
то есть move(dest[index+1],dest[index],sizeof(integer)*(high(dest)-index));

превращается в move(p[index+1],p[index],6*sizeof(integer)*(high(p)-index));
или как?
ZW
новенький
 
Сообщения: 26
Зарегистрирован: 16.08.2006 15:11:23

Сообщение debi12345 » 08.09.2006 08:26:00

Мда... до этого я бы фиг додумался:)

Если хотите - напишите баг-репорт (хотя 99% что это давно замечено).

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


Попробуйте sizeof(YOUR_TYPE), как в следующем примере :

//-------------
program test;

type

rec1 = record
tag: PChar;
data: integer;
end;

rec1arrty = array of rec1;

var

i: integer;
var1: rec1arrty;

procedure deleteitem(var dest: rec1arrty; index: integer);
begin
move(dest[index+1],dest[index],sizeof(rec1arrty)*(high(dest)-index));
setlength(dest,high(dest));
end;


begin
setlength(var1,3);

var1[0].tag:= 'mumu';
var1[0].data:= 1;

var1[1].tag:= 'bebe';
var1[1].data:= 2;

var1[2].tag:= 'gaga';
var1[2].data:= 3;

writeln(#13#10+'Before deletion:'+#13#10);
for i:= 0 to high(var1) do begin
writeln(var1[i].tag,'= ',var1[i].data);
end;

deleteitem(var1,1);

writeln(#13#10+'After deletion:'+#13#10);
for i:= 0 to high(var1) do begin
writeln(var1[i].tag,'= ',var1[i].data);
end;

end.
//----
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение jwv » 08.09.2006 10:43:07

ZW писал(а):Но каким образом считать память, что бы вынести элемент из двумерного массива?
Вернее из записи p[j].x[y]
То есть p : array of x;
можно ли рассматривать таким образом: если high(x)=5, то длина записи p[j] 6*integer
то есть move(dest[index+1],dest[index],sizeof(integer)*(high(dest)-index));

превращается в move(p[index+1],p[index],6*sizeof(integer)*(high(p)-index));
или как?


Если x это array of integer, то в p хранятся ссылки на масив.
т.е. независимо от того сколько элементов в x, размер элемента в p равен SizeOf(Pointer).
jwv
новенький
 
Сообщения: 21
Зарегистрирован: 10.05.2005 12:23:16

Сообщение ZW » 09.09.2006 01:53:02

работает нормально только при удалении последнего элемента:(
ZW
новенький
 
Сообщения: 26
Зарегистрирован: 16.08.2006 15:11:23

Сообщение debi12345 » 09.09.2006 03:14:54

ZW писал(а):работает нормально только при удалении последнего элемента:(

Вполне нормальная ситуация, если данные в памяти расположатся фрагментарно или в куче. "Move" сработает корректно только если для непрерывных областей. Поэтому позаботьтесь о минимальном размере данного массива - вместо больших элементов сохраняйте указатели на них, объявите глобально или статически, не дайте ему попасть в стек процедуры.
Если не удастся влезть в массив - придется отказаться от быстрой MOVE и вернутся к медленному и тупому линейному перебору, или вести индексы.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение ZW » 09.09.2006 11:38:28

debi12345 писал(а):
ZW писал(а):работает нормально только при удалении последнего элемента:(

Вполне нормальная ситуация, если данные в памяти расположатся фрагментарно или в куче. "Move" сработает корректно только если для непрерывных областей. Поэтому позаботьтесь о минимальном размере данного массива - вместо больших элементов сохраняйте указатели на них, объявите глобально или статически, не дайте ему попасть в стек процедуры.
Если не удастся влезть в массив - придется отказаться от быстрой MOVE и вернутся к медленному и тупому линейному перебору, или вести индексы.


мда.... учитывая что там три динамических массива на месте x. Выглядит все печально:(
как нехочется лезть в указатели...
ZW
новенький
 
Сообщения: 26
Зарегистрирован: 16.08.2006 15:11:23

Сообщение jwv » 09.09.2006 12:28:00

ZW писал(а):мда.... учитывая что там три динамических массива на месте x. Выглядит все печально:(
как нехочется лезть в указатели...


закинь сюда описание типа.
jwv
новенький
 
Сообщения: 21
Зарегистрирован: 10.05.2005 12:23:16

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 33

Рейтинг@Mail.ru