Echo_
01-31-2013, 02:01 AM
This is an implementation of a vector type. A vector is a container of elements like an array, but it can grow and shrink as you add and delete elements. Vectors are meant for adding elements to the end, as opposed to lists which are meant for adding elements to the front. Since I overloaded some functions, this will only be compatible with Lape. I also added a Map function just because I'm a big fan of functional programming :p
type
TVector = record
Size: Cardinal;
Elements: TVariantArray;
end;
{************************************************* ******************************
function Vector(Size: Cardinal): TVector;
by: Echo_
Description: Creates a new TVector with the given size.
************************************************** *****************************}
function Vector(Size: Cardinal): TVector; overload;
begin
Result.Size := Size;
SetLength(Result.Elements, Result.Size);
end;
{************************************************* ******************************
function Vector: TVector;
by: Echo_
Description: Creates a new TVector with a size of 0.
************************************************** *****************************}
function Vector: TVector; overload;
begin
Result := Vector(0);
end;
{************************************************* ******************************
function Vector(Elements: TVariantArray): TVector;
by: Echo_
Description: Creates a new TVector containing the given elements.
************************************************** *****************************}
function Vector(Elements: TVariantArray): TVector; overload;
var
I: Integer;
begin
Result := Vector(Length(Elements));
for I := 0 to High(Elements) do
Result.Elements[I] := Elements[I];
end;
{************************************************* ******************************
function TVector.IsEmpty: Boolean;
by: Echo_
Description: Returns true i the size is 0, false otherwise.
************************************************** *****************************}
function TVector.IsEmpty: Boolean;
begin
Result := Size = 0;
end;
{************************************************* ******************************
function TVector.IndexOf(X: Variant): Integer;
by: Echo_
Description: Returns the first index of X, -1 otherwise.
************************************************** *****************************}
function TVector.IndexOf(X: Variant): Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to Size - 1 do
if Elements[I] = X then begin
Result := I;
Break;
end;
end;
{************************************************* ******************************
function TVector.LastIndexOf(X: Variant): Integer;
by: Echo_
Description: Returns the last index of X, -1 otherwise.
************************************************** *****************************}
function TVector.LastIndexOf(X: Variant): Integer;
var
I: Integer;
begin
Result := -1;
for I := Size - 1 downto 0 do
if Elements[I] = X then begin
Result := I;
Break;
end;
end;
{************************************************* ******************************
function TVector.ContainsElement(X: Variant): Boolean;
by: Echo_
Description: True X is in the TVector, false otherwise.
************************************************** *****************************}
function TVector.ContainsElement(X: Variant): Boolean;
begin
Result := IndexOf(X) >= 0;
end;
{************************************************* ******************************
function TVector.GetElement(Index: Cardinal): Variant;
by: Echo_
Description: Returns the value at elements[index].
************************************************** *****************************}
function TVector.GetElement(Index: Cardinal): Variant;
begin
Result := Elements[Index];
end;
{************************************************* ******************************
procedure TVector.SetElement(Index: Cardinal; X: Variant);
by: Echo_
Description: Sets the value at elements[index] to x.
************************************************** *****************************}
procedure TVector.SetElement(Index: Cardinal; X: Variant);
begin
Elements[Index] := X;
end;
{************************************************* ******************************
procedure TVector.AddElement(X: Variant);
by: Echo_
Description: Adds X to the end of the TVector.
************************************************** *****************************}
procedure TVector.AddElement(X: Variant); overload;
begin
Inc(Size);
SetLength(Elements, Size);
Elements[Size - 1] := X;
end;
{************************************************* ******************************
procedure TVector.AddElement(X: Variant; Index: Cardinal);
by: Echo_
Description: Adds X at elements[index], shifting the remaining values right.
************************************************** *****************************}
procedure TVector.AddElement(X: Variant; Index: Cardinal); overload;
var
I: Integer;
A: TVariantArray;
begin
Inc(Size);
SetLength(Elements, Size);
for I := Size - 1 downto Index + 1 do
Elements[I] := Elements[I - 1];
Elements[Index] := X;
end;
{************************************************* ******************************
procedure TVector.AddElements(X: TVariantArray);
by: Echo_
Description: Adds X to the end of the TVector.
************************************************** *****************************}
procedure TVector.AddElements(X: TVariantArray); overload;
var
S, I: Integer;
begin
S := Size;
Size := Size + Length(X);
SetLength(Elements, Size);
for I := S to Size - 1 do
Elements[I] := X[I - S];
end;
{************************************************* ******************************
procedure TVector.AddElements(X: TVariantArray; Index: Cardinal);
by: Echo_
Description: Adds X at elements[index], shifting the remaining values right.
************************************************** *****************************}
procedure TVector.AddElements(X: TVariantArray; Index: Cardinal); overload;
var
I: Integer;
begin
Size := Size + Length(X);
SetLength(Elements, Size);
for I := Index + High(X) downto Index do
Elements[I + Length(X)] := Elements[I];
for I := 0 to High(X) do
Elements[I + Index] := X[I];
end;
{************************************************* ******************************
procedure TVector.DeleteElement(Index: Cardinal);
by: Echo_
Description: Deletes elements[index], shifting the remaining values left.
************************************************** *****************************}
procedure TVector.DeleteElement(Index: Cardinal);
var
I: Integer;
begin
for I := Index + 1 to Size - 1 do
Elements[I - 1] := Elements[I];
Dec(Size);
SetLength(Elements, Size);
end;
{************************************************* ******************************
procedure TVector.DeleteElements(Start, Finish: Cardinal);
by: Echo_
Description: Deletes elements between start (inclusive) and finish (exclusive).
************************************************** *****************************}
procedure TVector.DeleteElements(Start, Finish: Cardinal);
var
Offset, I: Integer;
begin
Offset := Finish - Start;
for I := Finish to Size - 1 do
Elements[I - Offset] := Elements[I];
Size := Size - Offset;
SetLength(Elements, Size);
end;
{************************************************* ******************************
procedure TVector.DeleteOccurrence(X: Variant);
by: Echo_
Description: Deletes the first element equal to X.
************************************************** *****************************}
procedure TVector.DeleteOccurrence(X: Variant);
var
Index: Integer;
begin
Index := IndexOf(X);
if Index = -1 then
Exit;
DeleteElement(Index);
end;
{************************************************* ******************************
procedure TVector.DeleteLastOccurrence(X: Variant);
by: Echo_
Description: Deletes the last element equal to X.
************************************************** *****************************}
procedure TVector.DeleteLastOccurrence(X: Variant);
var
Index: Integer;
begin
Index := LastIndexOf(X);
if Index = -1 then
Exit;
DeleteElement(Index);
end;
{************************************************* ******************************
procedure TVector.Clear;
by: Echo_
Description: Sets size to 0 and deletes all elements.
************************************************** *****************************}
procedure TVector.Clear;
begin
Size := 0;
SetLength(Elements, Size);
end;
{************************************************* ******************************
function Map(F: function(X: Variant): Variant; const V: TVector): TVector;
by: Echo_
Description: Applies function F to each element in V, returning a new TVector
containing the results.
************************************************** *****************************}
function Map(F: function(X: Variant): Variant; const V: TVector): TVector;
var
I: Integer;
begin
Result := Vector(V.Size);
for I := 0 to High(V.Elements) do
Result.SetElement(I, F(V.GetElement(I)));
end;
An example of how to use Map:
function Add2(A: Variant): Variant;
begin
Result := VarAsType(A, varInteger) + 2;
end;
var
A: TVariantArray;
X, Y: TVector;
begin
ClearDebug;
A := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
X := Vector(A);
Y := Map(@Add2, X);
WriteLn(X);
WriteLn(Y);
end.
This code will print:
{SIZE = 10, ELEMENTS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
{SIZE = 10, ELEMENTS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]}
Enjoy :)
type
TVector = record
Size: Cardinal;
Elements: TVariantArray;
end;
{************************************************* ******************************
function Vector(Size: Cardinal): TVector;
by: Echo_
Description: Creates a new TVector with the given size.
************************************************** *****************************}
function Vector(Size: Cardinal): TVector; overload;
begin
Result.Size := Size;
SetLength(Result.Elements, Result.Size);
end;
{************************************************* ******************************
function Vector: TVector;
by: Echo_
Description: Creates a new TVector with a size of 0.
************************************************** *****************************}
function Vector: TVector; overload;
begin
Result := Vector(0);
end;
{************************************************* ******************************
function Vector(Elements: TVariantArray): TVector;
by: Echo_
Description: Creates a new TVector containing the given elements.
************************************************** *****************************}
function Vector(Elements: TVariantArray): TVector; overload;
var
I: Integer;
begin
Result := Vector(Length(Elements));
for I := 0 to High(Elements) do
Result.Elements[I] := Elements[I];
end;
{************************************************* ******************************
function TVector.IsEmpty: Boolean;
by: Echo_
Description: Returns true i the size is 0, false otherwise.
************************************************** *****************************}
function TVector.IsEmpty: Boolean;
begin
Result := Size = 0;
end;
{************************************************* ******************************
function TVector.IndexOf(X: Variant): Integer;
by: Echo_
Description: Returns the first index of X, -1 otherwise.
************************************************** *****************************}
function TVector.IndexOf(X: Variant): Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to Size - 1 do
if Elements[I] = X then begin
Result := I;
Break;
end;
end;
{************************************************* ******************************
function TVector.LastIndexOf(X: Variant): Integer;
by: Echo_
Description: Returns the last index of X, -1 otherwise.
************************************************** *****************************}
function TVector.LastIndexOf(X: Variant): Integer;
var
I: Integer;
begin
Result := -1;
for I := Size - 1 downto 0 do
if Elements[I] = X then begin
Result := I;
Break;
end;
end;
{************************************************* ******************************
function TVector.ContainsElement(X: Variant): Boolean;
by: Echo_
Description: True X is in the TVector, false otherwise.
************************************************** *****************************}
function TVector.ContainsElement(X: Variant): Boolean;
begin
Result := IndexOf(X) >= 0;
end;
{************************************************* ******************************
function TVector.GetElement(Index: Cardinal): Variant;
by: Echo_
Description: Returns the value at elements[index].
************************************************** *****************************}
function TVector.GetElement(Index: Cardinal): Variant;
begin
Result := Elements[Index];
end;
{************************************************* ******************************
procedure TVector.SetElement(Index: Cardinal; X: Variant);
by: Echo_
Description: Sets the value at elements[index] to x.
************************************************** *****************************}
procedure TVector.SetElement(Index: Cardinal; X: Variant);
begin
Elements[Index] := X;
end;
{************************************************* ******************************
procedure TVector.AddElement(X: Variant);
by: Echo_
Description: Adds X to the end of the TVector.
************************************************** *****************************}
procedure TVector.AddElement(X: Variant); overload;
begin
Inc(Size);
SetLength(Elements, Size);
Elements[Size - 1] := X;
end;
{************************************************* ******************************
procedure TVector.AddElement(X: Variant; Index: Cardinal);
by: Echo_
Description: Adds X at elements[index], shifting the remaining values right.
************************************************** *****************************}
procedure TVector.AddElement(X: Variant; Index: Cardinal); overload;
var
I: Integer;
A: TVariantArray;
begin
Inc(Size);
SetLength(Elements, Size);
for I := Size - 1 downto Index + 1 do
Elements[I] := Elements[I - 1];
Elements[Index] := X;
end;
{************************************************* ******************************
procedure TVector.AddElements(X: TVariantArray);
by: Echo_
Description: Adds X to the end of the TVector.
************************************************** *****************************}
procedure TVector.AddElements(X: TVariantArray); overload;
var
S, I: Integer;
begin
S := Size;
Size := Size + Length(X);
SetLength(Elements, Size);
for I := S to Size - 1 do
Elements[I] := X[I - S];
end;
{************************************************* ******************************
procedure TVector.AddElements(X: TVariantArray; Index: Cardinal);
by: Echo_
Description: Adds X at elements[index], shifting the remaining values right.
************************************************** *****************************}
procedure TVector.AddElements(X: TVariantArray; Index: Cardinal); overload;
var
I: Integer;
begin
Size := Size + Length(X);
SetLength(Elements, Size);
for I := Index + High(X) downto Index do
Elements[I + Length(X)] := Elements[I];
for I := 0 to High(X) do
Elements[I + Index] := X[I];
end;
{************************************************* ******************************
procedure TVector.DeleteElement(Index: Cardinal);
by: Echo_
Description: Deletes elements[index], shifting the remaining values left.
************************************************** *****************************}
procedure TVector.DeleteElement(Index: Cardinal);
var
I: Integer;
begin
for I := Index + 1 to Size - 1 do
Elements[I - 1] := Elements[I];
Dec(Size);
SetLength(Elements, Size);
end;
{************************************************* ******************************
procedure TVector.DeleteElements(Start, Finish: Cardinal);
by: Echo_
Description: Deletes elements between start (inclusive) and finish (exclusive).
************************************************** *****************************}
procedure TVector.DeleteElements(Start, Finish: Cardinal);
var
Offset, I: Integer;
begin
Offset := Finish - Start;
for I := Finish to Size - 1 do
Elements[I - Offset] := Elements[I];
Size := Size - Offset;
SetLength(Elements, Size);
end;
{************************************************* ******************************
procedure TVector.DeleteOccurrence(X: Variant);
by: Echo_
Description: Deletes the first element equal to X.
************************************************** *****************************}
procedure TVector.DeleteOccurrence(X: Variant);
var
Index: Integer;
begin
Index := IndexOf(X);
if Index = -1 then
Exit;
DeleteElement(Index);
end;
{************************************************* ******************************
procedure TVector.DeleteLastOccurrence(X: Variant);
by: Echo_
Description: Deletes the last element equal to X.
************************************************** *****************************}
procedure TVector.DeleteLastOccurrence(X: Variant);
var
Index: Integer;
begin
Index := LastIndexOf(X);
if Index = -1 then
Exit;
DeleteElement(Index);
end;
{************************************************* ******************************
procedure TVector.Clear;
by: Echo_
Description: Sets size to 0 and deletes all elements.
************************************************** *****************************}
procedure TVector.Clear;
begin
Size := 0;
SetLength(Elements, Size);
end;
{************************************************* ******************************
function Map(F: function(X: Variant): Variant; const V: TVector): TVector;
by: Echo_
Description: Applies function F to each element in V, returning a new TVector
containing the results.
************************************************** *****************************}
function Map(F: function(X: Variant): Variant; const V: TVector): TVector;
var
I: Integer;
begin
Result := Vector(V.Size);
for I := 0 to High(V.Elements) do
Result.SetElement(I, F(V.GetElement(I)));
end;
An example of how to use Map:
function Add2(A: Variant): Variant;
begin
Result := VarAsType(A, varInteger) + 2;
end;
var
A: TVariantArray;
X, Y: TVector;
begin
ClearDebug;
A := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
X := Vector(A);
Y := Map(@Add2, X);
WriteLn(X);
WriteLn(Y);
end.
This code will print:
{SIZE = 10, ELEMENTS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
{SIZE = 10, ELEMENTS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]}
Enjoy :)