Array – How to make the array different

I have an array of integer and string fields. To make it different, I currently copy line by line to the new array, and each record checks whether the record already exists in new, if It’s not that I copied it. Finally, I copied the new array back to the original data.

It worked, but it was very slow. Is there a faster and easier way to do this?

TArrayMixed = record
Field1: integer;
Field2: integer;
Field3: integer;
Field4: string;< br /> Field5: string;
Field6: string;
end;

procedure TForm1.Button10Click(Sender: TObject);
var
ArrayMixed, ArrayMixed_tmp: array of TArrayMixed;
i, j, vIdx: integer;
vExists: boolean;
begin
SetLength(ArrayMixed, 100000);
for i := 0 to 99999 do
begin
ArrayMixed[i].Field1 := 1 + Random(5);
ArrayMixed[i].Field2 := 1 + Random(5);
ArrayMixed[i].Field3 := 1 + Random(5);
ArrayMixed[i].Field4 :='String';
ArrayMixed[i].Field5 :='Another string';< br /> ArrayMixed[i].Field6 :='New string';
end;

// Sort
TArray.Sort (ArrayMixed, TComparer .Construct(function(const Left, Right: TArrayMixed): Integer
begin
Result := MyCompareAMixed(Left, Right);
end
));

// Distinct
SetLength(ArrayMixed_tmp, Length(ArrayMixed));
vIdx := 0;
for i := Low(ArrayMixed) to High(ArrayMixed) do
begin
vExists := False;
for j := Low(ArrayMixed_tmp) to vIdx-1 do
if (ArrayMixed_tmp[j ].Field1 = ArrayMixed[i].Field1) and
(ArrayMixed_tmp[j].Field2 = ArrayMixed[i].Field2) and
(ArrayMixed_tmp[j].Field3 = ArrayMixed[i].Field3 ) and
(ArrayMixed_tmp[j].Field4 = ArrayMixed[i].Field4) and
(ArrayMixed_tmp[j].Field5 = ArrayMixed[i].Field5) and
(ArrayMixed_tmp[j ].Field6 = ArrayMixed[i].Field6) then
begin
vExists := True;
Break;
end;

if not vExists then
begin
ArrayMixed_tmp[vIdx] := ArrayMixed[i];
Inc(vIdx);
end;
end;
SetLength(ArrayMixed_tmp, vIdx );

// now copy back to original array
SetLengt h(ArrayMixed, 0);
SetLength(ArrayMixed, Length(ArrayMixed_tmp));
for i := Low(ArrayMixed_tmp) to High(ArrayMixed_tmp) do
ArrayMixed[i] := ArrayMixed_tmp [i];

sleep(0);

end;

Edit:

Because the string in the actual data It is not exactly the same, so when the original array is filled, it makes the part of the different array slower:

Edit #2: (copy the wrong code in edit #1)

< p>

for i := 0 to 999999 do
begin
ArrayMixed[i].Field1 := 1 + Random(5);
ArrayMixed[i]. Field2 := 1 + Random(5);
ArrayMixed[i].Field3 := 1 + Random(5);
ArrayMixed[i].Field4 :='String'+IntToStr(i mod 5 );
ArrayMixed[i].Field5 :='Another string'+IntToStr(i mod 5);
ArrayMixed[i].Field6 :='New string'+IntToStr( i mod 5);
end;

Edit #3: Post the code for sorting-only sort the first 3 fields!

TMyArray3 = array[1..3] of Integer;

function CompareIntegerArray3(const lhs, rhs: TMyArray3): Integer;
var
i: Integer;
begin
Assert(Length(lhs) = Length(rhs));
for i := low(lhs) to high(lhs) do
if lhs[i] exit(-1)
else if lhs[i]> rhs[i] then
exit(1);< br />
exit(0);
end;

function GetMyArrayAMixed(const Value: TArrayMixed): TMyArray3;
begin
Result[1] := Value.Field1;
Result[2] := Value.Field2;
Result[3] := Value.Field3;
end;

function MyCompareAMixed (const lhs, rhs: TArrayMixed): Integer;
begin
Result := CompareIntegerArray3(GetMyArrayAMixed(lhs), GetMyArrayAMixed(rhs));
end;

Just check the duplicates next to the previous index, because the array is already sorted. Here is also a sorting comparator for repeated use.

< /p>

fu nction RemoveDuplicates(const anArray: array of TArrayMixed): TArray;
var
j, vIdx: integer;
begin
// Sort
TArray.Sort (anArray, TComparer.Construct(function(const Left, Right: TArrayMixed): Integer
begin
Result := MyCompareAMixed(Left, Right);
end
));

// Distinct
SetLength(Result, Length(anArray));
vIdx := 0;
j := 0;
while (j <= High(anArray) do
begin
Result[vIdx] := anArray[j];
Inc(j);
While (j <= High(anArray)) and (MyCompareAMixed(Result[vIdx],anArray[j]) = 0) do
Inc(j);
Inc(vIdx);
end;
SetLength(Result, vIdx);
end;

Update:

In the update of the question, declare that the array is only partially sorted. Reduce the number of iterations to repeat One way is to:

>Find the start and stop indexes of the items that share the first sort criteria.>Iterate between them to solve the duplicate problem.

< /p>

I have an array of integer and string fields. To make it different, I currently copy to the new array line by line, and each record checks whether the record already exists in new, if not I copy it. Finally, I copy the new array back to the original data.

It works, but it is very slow. Is there a faster and easier way to do this?

TArrayMixed = record
Field1: integer;
Field2: integer;
Field3: integer;
Field4: string;< br /> Field5: string;
Field6: string;
end;

procedure TForm1.Button10Click(Sender: TObject);
var
ArrayMixed, ArrayMixed_tmp: array of TArrayMixed;
i, j, vIdx: integer;
vExists: boolean;
begin
SetLength(ArrayMixed, 100000);
for i := 0 to 99999 do
begin
ArrayMixed[i].Field1 := 1 + Random(5);
ArrayMixed[i].Field2 := 1 + Random(5);
ArrayMixed[i].Field3 := 1 + Random(5);
ArrayMixed[i].Field4 :='String';
ArrayMixed[i].Field5 :='Another string';< br /> ArrayMixed[i].Field6 :='New string';
end;

// Sort
TArray.Sort (ArrayMixed, TComparer .Construct(function(const Left, Right: TArrayMixed): Integer
begin
Result := MyCompareAMixed(Left, Right);
en d
));

// Distinct
SetLength(ArrayMixed_tmp, Length(ArrayMixed));
vIdx := 0;
for i := Low(ArrayMixed) to High(ArrayMixed) do
begin
vExists := False;
for j := Low(ArrayMixed_tmp) to vIdx-1 do
if (ArrayMixed_tmp[j ].Field1 = ArrayMixed[i].Field1) and
(ArrayMixed_tmp[j].Field2 = ArrayMixed[i].Field2) and
(ArrayMixed_tmp[j].Field3 = ArrayMixed[i].Field3 ) and
(ArrayMixed_tmp[j].Field4 = ArrayMixed[i].Field4) and
(ArrayMixed_tmp[j].Field5 = ArrayMixed[i].Field5) and
(ArrayMixed_tmp[j ].Field6 = ArrayMixed[i].Field6) then
begin
vExists := True;
Break;
end;

if not vExists then
begin
ArrayMixed_tmp[vIdx] := ArrayMixed[i];
Inc(vIdx);
end;
end;
SetLength(ArrayMixed_tmp, vIdx );

// now copy back to original array
SetLength( ArrayMixed, 0);
SetLength(ArrayMixed, Length(ArrayMixed_tmp));
for i := Low(ArrayMixed_tmp) to High(ArrayMixed_tmp) do
ArrayMixed[i] := ArrayMixed_tmp[i ];

sleep(0);

end;

Edit:

Because the string is not in the actual data It’s exactly the same, so when the original array is filled, it makes the parts of the different arrays slower:

Edit #2: (copy the wrong code in edit #1)

for i := 0 to 999999 do
begin
ArrayMixed[i].Field1 := 1 + Random(5);
ArrayMixed[i].Field2: = 1 + Random(5);
ArrayMixed[i].Field3 := 1 + Random(5);
ArrayMixed[i].Field4 :='String'+IntToStr(i mod 5);
ArrayMixed[i].Field5 :='Another string'+IntToStr(i mod 5);
ArrayMixed[i].Field6 :='New string'+IntToStr( i mod 5);
end;

Edit #3: Post the code for sorting-only sort the first 3 fields!

TMyArray3 = array[1..3] of Integer;

function CompareIntegerArray3(const lhs, rhs: TMyArray3): Integer;
var
i: Integer;
begin
Assert(Length(lhs) = Length(rhs));
for i := low(lhs) to high(lhs) do
if lhs[i] exit(-1)
else if lhs[i]> rhs[i] then
exit(1);< br />
exit(0);
end;

function GetMyArrayAMixed(const Value: TArrayMixed): TMyArray3;
begin
Result[1] := Value.Field1;
Result[2] := Value.Field2;
Result[3] := Value.Field3;
end;

function MyCompareAMixed (const lhs, rhs: TArrayMixed): Integer;
begin
Result := CompareIntegerArray3(GetMyArrayAMixed(lhs), GetMyArrayAMixed(rhs));
end;

Just check the duplicates next to the previous index, because the array is sorted. Here is also a sorting comparator for repeated use.

function RemoveDuplicates(const anArray: array of TArrayM ixed): TArray;
var
j, vIdx: integer;
begin
// Sort
TArray.Sort (anArray, TComparer< TArrayMixed >.Construct(function(const Left, Right: TArrayMixed): Integer
begin
Result := MyCompareAMixed(Left, Right);
end
));

// Distinct
SetLength(Result, Length(anArray));
vIdx := 0;
j := 0;
while (j <= High (anArray) do
begin
Result[vIdx] := anArray[j];
Inc(j);
While (j <= High(anArray)) and (MyCompareAMixed (Result[vIdx],anArray[j]) = 0) do
Inc(j);
Inc(vIdx);
end;
SetLength(Result, vIdx);
end;

Update:

In the update to the question, declare that the array is only partially sorted. One way to reduce the number of iterations is:

p>

>Find the start and stop indexes of the items that share the first sort condition.>Iterate between them to solve the duplicate problem.

Leave a Comment

Your email address will not be published.