This is a new site that's currently running on alpha code. There are going to be bugs. If you discover any, please report them on the site's issues page (GitHub account required). Thanks.
Warning: Many URLs are going to change. Refer to the README file to discover which library project's documentation has been completed.
Project: Array Utilities Unit
Unit: DelphiDabbler.Lib.ArrayUtils
Record: TArrayUtils
Applies to: ~>0.1
type
TConstraint<T> = reference to function (const AElem: T): Boolean;
TConstraintEx<T> = reference to function (const AElem: T;
const AIndex: Integer; const AArray: array of T): Boolean;
class function TryFindLast<T>(const A: array of T;
const AConstraint: TConstraint<T>; out AItem: T): Boolean;
overload; static;
class function TryFindLast<T>(const A: array of T;
const AConstraint: TConstraintEx<T>; out AItem: T): Boolean;
overload; static;
Attempts to find the last element of an array for which a given constraint function returns True
. Returns a Boolean
that indicates success or failure.
Parameters:
A - Array to be checked.
AConstraint - Constraint function called for each element of A. Returns True
if the element meets the required criteria or False
otherwise. AConstraint must be a function of type TConstraint<T> or TConstraintEx<T>.
Parameter(s):
Returns:
True
if AElem meets the required criteria, False
otherwise.AItem - Set to the last element of A for which AConstraint returns True
. Undefined if AConstraint returns False
, i.e. no such element is found.
Returns:
True
if A contains at least one element for which AConstraint returns True
is found, False
otherwise.The TConstraint<T> overload is all you need for most purposes. However there are cases where it is useful to have access to the whole array or the element’s index within the array, which is the reason the TConstraintEx<T> overload is provided.
The first example finds the last element of an integer array that is ≥ 4
. We only need the simple TConstraint<T> overload.
procedure TryFindLast_Eg1;
var
A, B: TArray<Integer>;
Found: Integer;
Constraint: TArrayUtils.TConstraint<Integer>;
begin
A := TArray<Integer>.Create(1, 2, 3, 4, 5, 3);
B := TArray<Integer>.Create(1, 2, 3);
Constraint := function (const AElem: Integer): Boolean
begin
Result := AElem >= 4;
end;
Assert(TArrayUtils.TryFindLast<Integer>(A, Constraint, Found) = True);
Assert(Found = 5);
Assert(TArrayUtils.TryFindLast<Integer>(B, Constraint, Found) = False);
// `Found` is undefined
end;
The second example finds the last local maximum in an array of integers. To do this we need to be able to access the array element before and after a given element. Therefore the TConstraintEx<T> overload of TryFindLast<T> is required.
procedure TryFindLast_Eg2;
var
IsLocalMaxElem: TArrayUtils.TConstraintEx<Integer>;
A, B: TArray<Integer>;
Found: Integer;
begin
IsLocalMaxElem :=
function (const AElem: Integer; const AIndex: Integer;
const A: array of Integer): Boolean
begin
if Length(A) = 0 then
// no local maxima in an empty array
Exit(False);
if Length(A) = 1 then
// the only element in a 1 element array is considered to be a maximum
Exit(True);
// Length(A) >= 2
if (AIndex = 0) then
// 1st elem: peak if next elem smaller
Result := A[Succ(AIndex)] < AElem
else if AIndex = Pred(Length(A)) then
// last elem: peak if previous elem smaller
Result := A[Pred(AIndex)] < AElem
else
// not 1st or last: peak if > than elems on either side
Result := (A[Succ(AIndex)] < AElem) and (A[Pred(AIndex)] < AElem);
end;
A := TArray<Integer>.Create(1, 2, 3, 2, 3, 5, 1);
Assert(TArrayUtils.TryFindLast<Integer>(A, IsLocalMaxElem, Found) = True);
Assert(Found = 5);
B := TArray<Integer>.Create(1, 1, 1, 1);
Assert(TArrayUtils.TryFindLast<Integer>(B, IsLocalMaxElem, Found) = False);
// Found is not defined
end;