SRL Archive - Help and Support

Removing Duplicates From an Array?


Special Ed

2007-09-05 17:20:10

Just wondering if anyone could give me a handy function or some help on removing duplicate numbers from an array. What I'm trying to do is get InvSlots for each of the Fishing Equips (Fishing Rod, Net, ect…) and make an array of those slots. Problem is, is that sometimes it will return something like 1,2,3,3,3,4 and that makes the script store extra variables I don't want, because later when I make it look for something in those slots instead of looking in "3" once it will look there 3 times, there-for making it less efficient.

I've got it all done except for this part.

P.S. Any ideas on why DropExcept doesn't work?

Starblaster100

2007-09-05 17:37:57

[php]
program New;

var
MyArray, MyArray2: Array of Variant;
i, Mark: Integer;


procedure MarkTime(var TimeMarker: Integer);
begin
TimeMarker := GetSystemTime;
end;

function TimeFromMark(var TimeMarker: Integer): Integer;
begin
Result := GetSystemTime - TimeMarker;
end;


{——————————————————————————-
| procedure Debug(What: Variant); |
| So I can simply Writeln any Array Type without worying about IntToStr etc. |
——————————————————————————-}

procedure Debug(What: Variant);
begin
Writeln(What);
end;

{——————————————————————————-
| function DelInArray(IndexNo: Integer; InArray: TVariantArray): TVariantArray |
| Deletes the Index No. from the Input Array and Outputs the Result |
——————————————————————————-}

function DelInArray(IndexNo: Integer; InArray: TVariantArray): TVariantArray;
var
i: Integer;
begin
SetArrayLength(Result, GetArrayLength(InArray)-1);
If (GetArrayLength(InArray) <> IndexNo) then
begin
For i := 0 to IndexNo-1 do
Result := InArray;
For i := IndexNo to GetArrayLength(InArray)-1 do
Result[i-1] := InArray;
end else
For i := 0 to GetArrayLength(Result)-1 do
Result := InArray;
end;

{——————————————————————————-
| Main Loop |
——————————————————————————-}

begin
ClearDebug;
MyArray := ['a','b','c','d','e','f','g']; //Setup a Test Array
//MyArray := [1, 2, 3, 4, 5, 6, 7, 8];

MarkTime(Mark);
MyArray2 := DelInArray(4, MyArray); //Delete the specified index Number
Writeln(IntToStr(TimeFromMark(Mark)));

For i := 0 to GetArrayLength(MyArray2)-1 do //Print the Result
Debug(MyArray2);
end.
[/php]

Thats a start, removing from the Array. Dunno how you're gonna find if it s a dupe though

Special Ed

2007-09-05 17:45:45

Hey thanks a bunch, but yea, I don't know how I'm going to find if there's a duplicate, I thought possibly doing something like

for i:= 0 to GetArrayLength(Array) - 1 do
for e:= 0 to GetArrayLength(Array) - 1 do
if(Array[a] = Array[e])then BadArray:= e;

Wow… would that actually work? I just started typing this on SRL and then actually looked at it.

EDIT: Hmm… but how would I make sure it skips one instance of the Array?

Town

2007-09-05 18:00:47

procedure ShrinkArray(var Arrays: Array of Integer);
var
Arrayz: Array of Integer;
p, i: Integer;
begin
for i := 0 to GetArrayLength(Arrays) - 1 do
for p := 0 to GetArrayLength(Arrays) - 1 do
if (not (Arrays[p] = 0)) and (not (p = i)) and (Arrays[p] = Arrays[i]) then Arrays[p] := 0;
// for p := 0 to GetArrayLength(Arrays) - 1 do
// WriteLN(IntToStr(Arrays[p]));
p := 0;
for i := 0 to GetArrayLength(Arrays) - 1 do
begin
if (not (Arrays[i] = 0)) then
begin
SetArrayLength(Arrayz, GetArrayLength(Arrayz) + 1);
Arrayz[p] := Arrays[i];
p := p + 1;
end;
end;
SetArrayLength(Arrays, GetArrayLength(Arrayz));
for i := 0 to GetArrayLength(Arrays) - 1 do
Arrays[i] := Arrayz[i];
// WriteLN(' ');
// for i := 0 to GetArrayLength(Arrays) - 1 do
// WriteLN(IntToStr(Arrays[i]));
end;

var
Arrays: Array of Integer;
i: Integer;
begin
Arrays := [0, 0, 0, 1, 1, 2, 3, 4, 5, 5, 6, 6, 7, 6, 5];
ShrinkArray(Arrays);
for i := 0 to GetArrayLength(Arrays) - 1 do
WriteLN(IntToStr(Arrays[i]));
end.

Like that?

(I edited this post at least 4 times after I posted it all within 10 seconds of each other, it's right now).

bullzeye95

2007-09-05 18:08:35

Probably slower than it can be, but:
function DelInArray(IndexNo: Integer; InArray: TVariantArray): TVariantArray;  //starblaster100
var
i: Integer;
begin
SetArrayLength(Result, GetArrayLength(InArray)-1);
If (GetArrayLength(InArray) <> IndexNo) then
begin
For i := 0 to IndexNo-1 do
Result[i] := InArray[i];
For i := IndexNo to GetArrayLength(InArray)-1 do
Result[i-1] := InArray[i];
end else
For i := 0 to GetArrayLength(Result)-1 do
Result[i] := InArray[i];
end;

procedure RemoveDuplicates(var I: TIntegerArray);
var
x, y, z: Integer;
begin
while z < Length(I) do
begin
x:= Length(I);
inc(z);
while x > 0 do
begin
y:= 0;
while y < Length(I) do
begin
// AddToReport(inttostr(x) + ', ' + inttostr(y) + ', ' + inttostr(z));
try
if(not(x = y))then
if(I[x] = I[y])then
begin
I:= DelInArray(y, I);
continue;
end;
except
end;
inc(y);
end;
// ClearReport;
dec(x);
end;
end;
end;
That'll mess the order of it up though. If you don't want it to, then just replace my DeleteIntArrValue or whatever with his.
;)

EDIT: z0mg, star's delete thing is faster than mine!!!!!!!1111

Special Ed

2007-09-05 18:21:24

Hey, thanks Town / bullzeye, I think I'm going to stick with towns though, since his was the closest to was I was doing… I think I figured out what I was doing wrong too.

bullzeye95

2007-09-05 18:22:57

WTF, I could've sworn his wasn't working for me a second ago. That's why I posted that =/

Ok, carry on.

EDIT: Faster:
function InIntArr(Num: Integer; I: TIntegerArray): Boolean;
var
C: Integer;
begin
for C:= 0 to Length(I) - 1 do
if(I[C] = Num)then
begin
Result:= True;
exit;
end;
end;

procedure ShrinkArray(var Arr: TIntegerArray);
var
Used: TIntegerArray;
I, Index: Integer;
begin
SetLength(Used, Length(Arr));
if(InIntArr(0, Arr))then
Inc(Index);
for I:= 0 to Length(Arr) - 1 do
if(not(InIntArr(Arr[I], Used)))then
begin
Used[Index]:= Arr[I];
Inc(Index);
end;
SetLength(Used, Index);
Arr:= Used;
end;

Special Ed

2007-09-05 18:36:09

Lol… he was editing it, but when I tried it, it did work so… yea lol :D

Town

2007-09-05 19:19:04

Heh, I forgot to put var Arrays: Array of Integer when calling the procedure.

Wizzup?

2007-09-06 02:47:27

Function NumberDoesntExist(Ar2: Array Of Integer; Number: Integer): Boolean;

Var
I: Integer;
Begin
Result := False;
For I := 0 To GetArrayLength(Ar2) - 1 Do
Begin
If Ar2[I] = Number Then
Exit;
End;
Result := True;
End;

Function ShrinkArray(YourArray: Array Of Integer): Array Of Integer;

Var
I: Integer;

Begin
SetArrayLength(Result, 0);
For I := 0 To GetArrayLength(YourArray) - 1 Do
Begin
If NumberDoesntExist(Result, YourArray[I]) Then
Begin
SetArrayLength(Result, GetArrayLength(Result) + 1);
Result[GetArrayLength(Result) - 1] := YourArray[I];
End;
End;
End;

An old one, from my edgeville fisher.
Going to run it today, then probably post. :)

EDIT: I can probably make one with Swap too for extra speed?

mastaraymond

2007-09-06 09:20:09

Like this? :-)
function RemoveDups(Ints : TIntegerArray): TIntegerArray;
var
L,LL,I,II : Integer;
Bla : Boolean;
begin;
LL := GetArrayLength(Ints);
SetArrayLength(Result,LL);
L := 0;
For I:= 0 to LL-1 do
begin;
Bla := False;
For II := 0 to L-1 do
if Ints[I] = Result[II] then
begin;
Bla := True;
Break;
end;
if not bla then
begin;
Result[L] := Ints[I];
L := L +1;
end;
end;
SetArrayLength(Result,L);
end;
Mine = The fast ofcourse :')

Boreas

2007-09-06 10:14:08

For TPAs if you need it

program New;
{.include SRL/SRL.scar}
var
mytpa,newtpa:array of tpoint;

function RearrangeTPA(thearray:array of tpoint; startpt, endpt:integer; dox,up:boolean):array of tpoint;
var
temp, pArray : integer;
done : boolean;
ttp:tpoint;
tmpTPA : array of tpoint;
begin
setarraylength(tmpTPA,getarraylength(thearray));
tmpTPA:=thearray;
setarraylength(result,endpt+1-startpt);

if not(up) then
begin

if dox then
begin
repeat
done := true;
for pArray := 0 to (getarraylength(thearray) - 2) do
begin
if(tmpTPA[pArray].x < tmpTPA[pArray + 1].x) then
begin
ttp := tmpTPA[pArray];
tmpTPA[pArray] := tmpTPA[pArray + 1];
tmpTPA[pArray + 1] := ttp;
done := false;
end;
end;
until(done);
end;

if not(dox) then
begin
repeat
done := true;
for pArray := 0 to (getarraylength(thearray) - 2) do
begin
if(tmpTPA[pArray].y < tmpTPA[pArray + 1].y) then
begin
ttp := thearray[pArray];
tmpTPA[pArray] := tmpTPA[pArray + 1];
tmpTPA[pArray + 1] := ttp;

done := false;
end;
end;
until(done);
end;

end;

if up then
begin

if dox then
begin
repeat
done := true;
for pArray := 0 to (getarraylength(thearray) - 2) do
begin
if(tmpTPA[pArray].x > tmpTPA[pArray + 1].x) then
begin
ttp := tmpTPA[pArray];
tmpTPA[pArray] := tmpTPA[pArray + 1];
tmpTPA[pArray + 1] := ttp;

done := false;
end;
end;
until(done);
end;

if not(dox) then
begin
repeat
done := true;
for pArray := 0 to (getarraylength(thearray) - 2) do
begin
if(tmpTPA[pArray].y > tmpTPA[pArray + 1].y) then
begin
ttp := tmpTPA[pArray];
tmpTPA[pArray] := tmpTPA[pArray + 1];
tmpTPA[pArray + 1] := ttp;


done := false;
end;
end;
until(done);
end;

end;

pArray:=startpt-1;
for temp:=0 to getarraylength(result)-1 do
begin
pArray:=pArray+1;
result[temp]:=tmpTPA[pArray];
end;

end;
function tPtArrayToStr(newTPoint: TPointArray): string;
var
i: Integer;
begin
for i:=0 to GetArrayLength(newTPoint)-1 do
begin
Result := Result + IntToStr(newTPoint[i].x) + ',' +
IntToStr(newTPoint[i].y);
if (not (i = (GetArrayLength(newTPoint) - 1))) then
Result := Result + ' ';
end;
end;
function strToTPtArray(tPtStr: string): TPointArray;
var
i, commaPos, spacePos: Integer;
begin
repeat
SetArrayLength(Result, i + 1);
commaPos := Pos(',', tPtStr);
spacePos := Pos(' ', tPtStr);
Result[i].x := StrToInt(Copy(tPtStr, 1, commaPos - 1));
if (not (spacePos = 0)) then
begin
Result[i].y := StrToInt(Copy(tPtStr, commaPos + 1, spacePos - commaPos -
1));
end
else
begin
Result[i].y := StrToInt(Copy(tPtStr, commaPos + 1, Length(tPtStr)));
break;
end;
Delete(tPtStr, 1, spacePos);
i := i + 1;
until (False)
end;

function RemoveDupsFromTPA(var StartTPA: array of Tpoint): array of Tpoint;
var
ArrayLength, pFindDups, pBubbleUp: integer;
tpSwap:tpoint;
begin
ArrayLength:=getarraylength(StartTPA);
result:=RearrangeTPA(StartTPA,0,ArrayLength-1,true,true);
for pFindDups := 0 to (ArrayLength - 2) do
begin
if(result[pFindDups].x = result[pFindDups + 1].x) then
begin
if (result[pFindDups].y = result[pFindDups + 1].y)then
begin
for pBubbleUp := pFindDups to (ArrayLength-2) do
begin
tpSwap := result[pBubbleUp];
result[pBubbleUp] := result[pBubbleUp+1];
result[pBubbleUp+1] := tpSwap;
end;
ArrayLength := ArrayLength-1;
setarraylength(result, ArrayLength);
end;
end;
end;
end;


begin
mytpa:=strToTPtArray('656,62 701,73 645,79 656,62 661,88 621,93 700,110 621,93 653,119');
newtpa:=RemoveDupsFromTPA(mytpa);
writeln(tPtArrayToStr(newtpa));
//newtpa:= RearrangeTPA(mytpa, 0, 1,false,true);
end.

mastaraymond

2007-09-06 10:20:06

From: Boreas
For TPAs if you need it

program New;
{.include SRL/SRL.scar}
var
mytpa,newtpa:array of tpoint;

function RearrangeTPA(thearray:array of tpoint; startpt, endpt:integer; dox,up:boolean):array of tpoint;
var
temp, pArray : integer;
done : boolean;
ttp:tpoint;
tmpTPA : array of tpoint;
begin
setarraylength(tmpTPA,getarraylength(thearray));
tmpTPA:=thearray;
setarraylength(result,endpt+1-startpt);

if not(up) then
begin

if dox then
begin
repeat
done := true;
for pArray := 0 to (getarraylength(thearray) - 2) do
begin
if(tmpTPA[pArray].x < tmpTPA[pArray + 1].x) then
begin
ttp := tmpTPA[pArray];
tmpTPA[pArray] := tmpTPA[pArray + 1];
tmpTPA[pArray + 1] := ttp;
done := false;
end;
end;
until(done);
end;

if not(dox) then
begin
repeat
done := true;
for pArray := 0 to (getarraylength(thearray) - 2) do
begin
if(tmpTPA[pArray].y < tmpTPA[pArray + 1].y) then
begin
ttp := thearray[pArray];
tmpTPA[pArray] := tmpTPA[pArray + 1];
tmpTPA[pArray + 1] := ttp;

done := false;
end;
end;
until(done);
end;

end;

if up then
begin

if dox then
begin
repeat
done := true;
for pArray := 0 to (getarraylength(thearray) - 2) do
begin
if(tmpTPA[pArray].x > tmpTPA[pArray + 1].x) then
begin
ttp := tmpTPA[pArray];
tmpTPA[pArray] := tmpTPA[pArray + 1];
tmpTPA[pArray + 1] := ttp;

done := false;
end;
end;
until(done);
end;

if not(dox) then
begin
repeat
done := true;
for pArray := 0 to (getarraylength(thearray) - 2) do
begin
if(tmpTPA[pArray].y > tmpTPA[pArray + 1].y) then
begin
ttp := tmpTPA[pArray];
tmpTPA[pArray] := tmpTPA[pArray + 1];
tmpTPA[pArray + 1] := ttp;


done := false;
end;
end;
until(done);
end;

end;

pArray:=startpt-1;
for temp:=0 to getarraylength(result)-1 do
begin
pArray:=pArray+1;
result[temp]:=tmpTPA[pArray];
end;

end;
function tPtArrayToStr(newTPoint: TPointArray): string;
var
i: Integer;
begin
for i:=0 to GetArrayLength(newTPoint)-1 do
begin
Result := Result + IntToStr(newTPoint[i].x) + ',' +
IntToStr(newTPoint[i].y);
if (not (i = (GetArrayLength(newTPoint) - 1))) then
Result := Result + ' ';
end;
end;
function strToTPtArray(tPtStr: string): TPointArray;
var
i, commaPos, spacePos: Integer;
begin
repeat
SetArrayLength(Result, i + 1);
commaPos := Pos(',', tPtStr);
spacePos := Pos(' ', tPtStr);
Result[i].x := StrToInt(Copy(tPtStr, 1, commaPos - 1));
if (not (spacePos = 0)) then
begin
Result[i].y := StrToInt(Copy(tPtStr, commaPos + 1, spacePos - commaPos -
1));
end
else
begin
Result[i].y := StrToInt(Copy(tPtStr, commaPos + 1, Length(tPtStr)));
break;
end;
Delete(tPtStr, 1, spacePos);
i := i + 1;
until (False)
end;

function RemoveDupsFromTPA(var StartTPA: array of Tpoint): array of Tpoint;
var
ArrayLength, pFindDups, pBubbleUp: integer;
tpSwap:tpoint;
begin
ArrayLength:=getarraylength(StartTPA);
result:=RearrangeTPA(StartTPA,0,ArrayLength-1,true,true);
for pFindDups := 0 to (ArrayLength - 2) do
begin
if(result[pFindDups].x = result[pFindDups + 1].x) then
begin
if (result[pFindDups].y = result[pFindDups + 1].y)then
begin
for pBubbleUp := pFindDups to (ArrayLength-2) do
begin
tpSwap := result[pBubbleUp];
result[pBubbleUp] := result[pBubbleUp+1];
result[pBubbleUp+1] := tpSwap;
end;
ArrayLength := ArrayLength-1;
setarraylength(result, ArrayLength);
end;
end;
end;
end;


begin
mytpa:=strToTPtArray('656,62 701,73 645,79 656,62 661,88 621,93 700,110 621,93 653,119');
newtpa:=RemoveDupsFromTPA(mytpa);
writeln(tPtArrayToStr(newtpa));
//newtpa:= RearrangeTPA(mytpa, 0, 1,false,true);
end.
Uh, His question was about IntegerArrays not TPA's :p.

n3ss3s

2007-09-06 11:02:52

k here comes bullzeye with his shortened snippets :D

Guys I dont think you need that much code to remove duplicates.

First make a function that detects if a duplicate exists, and returns its IndexNumber, then, it creates an additional array slot, swaps the values (Swap)of the dupe slot, and the additional slot which makes additional slots value the dupe slot value, and dupe slot value null/0, then, remove the additional slot and move the indexes > Dupe slots index number backwards one step.

mastaraymond

2007-09-06 11:10:42

From: n3ss3s
k here comes bullzeye with his shortened snippets :D

Guys I dont think you need that much code to remove duplicates.

First make a function that detects if a duplicate exists, and returns its IndexNumber, then, it creates an additional array slot, swaps the values (Swap)of the dupe slot, and the additional slot which makes additional slots value the dupe slot value, and dupe slot value null/0, then, remove the additional slot and move the indexes > Dupe slots index number backwards one step.
Mine is shortest and fastest :rolleyes:.

Boreas

2007-09-06 11:33:32

Ray that's why I said- For TPAs if you need it

Wizzup?

2007-09-06 12:18:20

From: mastaraymond
Mine is shortest and fastest :rolleyes:.


You shouldn't always think that everything you code is the fastest…

Oh and please don't start doing speed tests with that code I posted there, it's a quite old already.

n3ss3s

2007-09-06 12:30:48

Hehe :)

Speaking of time, there is some kind of bug in time from mark.

if I make a marker, do 1000 FastGetPixels and then writeln time from mark
it says it took 0 ms, but with 2000 it says it took 16?

Starblaster100

2007-09-06 12:50:17

n3ss3s, run that script a few times. You will see it constantly jumps around the numbers 0 ms, and 16 ms. Thats just the way it is.

mastaraymond

2007-09-06 13:06:29

From: Wizzup?
You shouldn't always think that everything you code is the fastest…

Oh and please don't start doing speed tests with that code I posted there, it's a quite old already.
I laughed x). Im not ALWAYS thinking my code is the fastest, but 99% i do ^^.

Wizzup?

2007-09-06 13:47:35

From: n3ss3s
Hehe :)

Speaking of time, there is some kind of bug in time from mark.

if I make a marker, do 1000 FastGetPixels and then writeln time from mark
it says it took 0 ms, but with 2000 it says it took 16?


Getsystemtime time is accurate in 16 ms. ;)
Wait is also accurate in 16 ms, rounded up.
wait(1) waits 16 ms.

Special Ed

2007-09-06 16:29:32

Hey thanks guys, and yes speed would be greatly appreciated and Boreas thanks for the TPA one I'm going to need that soon too. :D

Also does anyone know why DropExcept doesn't work? I couldn't probably fix but if Dev's want to fix it in the SvN, thats their deal.

bullzeye95

2007-09-06 16:39:04

Oops, I speed tested them before I saw your post wizzup? :p

Mastaraymond's was the fastest with about 3750 ms for 1000 times (my computer and array…). Wizzup? next with about 4250 ms (again, my computer and array). And then mine… 8688 ms… I feel so embarrassed :(

Bobarkinator

2007-09-06 23:16:05

From: Wizzup?
Getsystemtime time is accurate in 16 ms. ;)
Wait is also accurate in 16 ms, rounded up.
wait(1) waits 16 ms.


Not always. I was testing it the other day with a game running it it took 16 ms then closed the game and it took 0 ms.

Wizzup?

2007-09-07 03:02:05

From: bobarkinator
Not always. I was testing it the other day with a game running it it took 16 ms then closed the game and it took 0 ms.


Heh, with the rounded up, I meant SCAR's wait.
I'm pretty sure wait(1) always waits 16 (sometimes 15, lol) ms. ;)

program New;

var
I1: integer;
begin
i1 := getsystemtime;
wait(1);
writeln(inttostr(getsystemtime - i1));
end.

program New;

var
I1: integer;
begin
i1 := getsystemtime;
wait(17);
writeln(inttostr(getsystemtime - i1));
end.

Bobarkinator

2007-09-08 00:28:26

Successfully compiled
0
Successfully executed


0 for me

Successfully compiled
16
Successfully executed

Wait(17) waited 16 for me