Reduce<T> class method

Project: Array Utilities Unit

Unit: DelphiDabbler.Lib.ArrayUtils

Record: TArrayUtils

Applies to: ~>0.1

type
  TReducer<T> = reference to function (const AAccumulator, ACurrent: T): T;
  TReducerEx<T> = reference to function (const AAccumulator, ACurrent: T;
    const AIndex: Integer; const AArray: array of T): T;

class function Reduce<T>(const A: array of T;
  const AReducer: TReducer<T>): T;
  overload; static;

class function Reduce<T>(const A: array of T; const AReducer: TReducer<T>;
  const AInitialValue: T): T;
  overload; static;

class function Reduce<T>(const A: array of T; const AReducer: TReducerEx<T>;
  const AInitialValue: T): T;
  overload; static;

Description

Reduces the elements of an array to a single value of the same type as the array elements.

Parameters:

Returns:

Precondition:

Examples

Example #1

The first example uses the 1st overload of Reduce<T>, which requires a non-empty array. The example computes the sum of a given integer array.

procedure Reduce_SingleType_Eg1;
var
  A: TArray<Integer>;
  SumCallback: TArrayUtils.TReducer<Integer>;
begin
  SumCallback := function (const AAccumulator, ACurrent: Integer): Integer
    begin
      Result := ACurrent + AAccumulator;
    end;
  A := TArray<Integer>.Create(1, 3, 5, 7, 9);
  Assert(TArrayUtils.Reduce<Integer>(A, SumCallback) = 25);
end;

Example #2

The second example exercises the 2nd Reduce<T> overload, using the AInitialValue parameter and the simple TReducer<T> callback function. The code demonstrates how to cumulatively add multiple arrays.

procedure Reduce_SingleType_Eg2;
var
  A, B: TArray<Integer>;
  SumCallback: TArrayUtils.TReducer<Integer>;
  RunningTotal: Integer;
begin
  SumCallback := function (const AAccumulator, ACurrent: Integer): Integer
    begin
      Result := ACurrent + AAccumulator;
    end;
  A := TArray<Integer>.Create(1, 3, 5, 7, 9);   // sum = 25
  B := TArray<Integer>.Create(2, 4, 6, 8, 10);  // sum = 30
  RunningTotal := 0;
  RunningTotal := TArrayUtils.Reduce<Integer>(A, SumCallback, RunningTotal);
  Assert(RunningTotal = 25);
  RunningTotal := TArrayUtils.Reduce<Integer>(B, SumCallback, RunningTotal);
  Assert(RunningTotal = 55);
end;

Example #3

The final example sums the absolute distances between adjacent elements of an integer array. It uses the 3rd Reduce<T> overload, using the AInitialValue and the more complex TReducerEx<T> callback function.

procedure Reduce_SingleType_Eg3;
var
  SumDistancesReducer: TArrayUtils.TReducerEx<Integer>;
  A: TArray<Integer>;
begin
  // Adds the absolute distances between adjacent elements of an integer array
  SumDistancesReducer := function (const AAccumulator, ACurrent: Integer;
    const AIndex: Integer; const AArray: array of Integer): Integer
    var
      Distance: Integer;
    begin
      Result := AAccumulator;
      if AIndex = 0 then
        Exit;
      Distance := Abs(AArray[AIndex] - AArray[AIndex - 1]);
      Result := Result + Distance;
    end;

  A := TArray<Integer>.Create(3, 6, 3, 8, 3, 2);
  Assert(TArrayUtils.Reduce<Integer>(A, SumDistancesReducer, 0) = 17);
end;

See Also