uses SysUtils, Math; type TArrayHelper = record helper for TArray<Double> strict private type TForEachRef = reference to procedure(X: Double; I: Integer; var Done: Boolean); TMapRef = reference to function(X: Double): Double; TFilterRef = reference to function(X: Double; I: Integer): Boolean; TPredicateRef = reference to function(X: Double): Boolean; TReduceRef = reference to function(Accumulator, X: Double): Double; public function ToString: string; procedure ForEach(Lambda: TForEachRef); function Map(Lambda: TMapRef): TArray<Double>; function Filter(Lambda: TFilterRef): TArray<Double>; function Every(Lambda: TPredicateRef): Boolean; function Some(Lambda: TPredicateRef): Boolean; function Reduce(Lambda: TReduceRef): Double; overload; function Reduce(Init: Double; Lambda: TReduceRef): Double; overload; function ReduceRight(Lambda: TReduceRef): Double; end;
var A: TArray<Double>; begin A := [1, 2, 3]; // XE7 // 2 A.ForEach(procedure(X: Double; I: Integer; var Done: Boolean) begin A[I] := X * 2; if I = 1 then Done := True; // ForEach end); WriteLn(A.ToString); // => [2, 4, 3] end;
procedure TArrayHelper.ForEach(Lambda: TForEachRef); var I: Integer; Done: Boolean; begin Done := False; for I := 0 to High(Self) do begin Lambda(Self[I], I, Done); if Done then Break; end; end; // : function TArrayHelper.ToString: string; var Res: TArray<string>; begin if Length(Self) = 0 then Exit('[]'); ForEach(procedure(X: Double; I: Integer; var Done: Boolean) begin Res := Res + [FloatToStr(X)]; end); Result := '[' + string.Join(', ', Res) + ']'; end;
var A, R: TArray<Double>; begin A := [1, 2, 3]; // R := A.Map(function(X: Double): Double begin Result := X * X; end); WriteLn(R.ToString); // => [1, 4, 9] end;
function TArrayHelper.Map(Lambda: TMapRef): TArray<Double>; var X: Double; begin for X in Self do Result := Result + [Lambda(X)]; end;
var Data: TArray<Double>; MidValues: TArray<Double>; begin Data := [5, 4, 3, 2, 1]; // , 1, 5 MidValues := Data.Filter(function(X: Double; I: Integer): Boolean begin Result := (1 < X) and (X < 5); end); WriteLn(MidValues.ToString); // => [4, 3, 2] // Data .Map(function(X: Double): Double begin Result := X + 5; // 5. end) .Filter(function(X: Double; I: Integer): Boolean begin Result := (I mod 2 = 0); // end) .ForEach(procedure(X: Double; I: Integer; var Done: Boolean) begin Write(X:2:0) // => 10 8 6 end); end;
function TArrayHelper.Filter(Lambda: TFilterRef): TArray<Double>; var I: Integer; begin for I := 0 to High(Self) do if Lambda(Self[I], I) then Result := Result + [Self[I]]; end;
var A: TArray<Double>; B: Boolean; begin A := [1, 2.7, 3, 4, 5]; B := A.Every(function(X: Double): Boolean begin Result := (X < 10); end); WriteLn(B); // => True: < 10. B := A.Every(function(X: Double): Boolean begin Result := (Frac(X) = 0); end); WriteLn(B); // => False: . end;
var A: TArray<Double>; B: Boolean; begin A := [1, 2.7, 3, 4, 5]; B := A.Some(function(X: Double): Boolean begin Result := (Frac(X) = 0); end); WriteLn(B); // => True: . end;
function TArrayHelper.Every(Lambda: TPredicateRef): Boolean; var X: Double; begin Result := True; for X in Self do if not Lambda(X) then Exit(False); end; function TArrayHelper.Some(Lambda: TPredicateRef): Boolean; var X: Double; begin Result := False; for X in Self do if Lambda(X) then Exit(True); end;
var A: TArray<Double>; Total, Product, Max: Double; begin A := [1, 2, 3, 4, 5]; // Total := A.Reduce(0, function(X, Y: Double): Double begin Result := X + Y; end); WriteLn(Total); // => 15.0 // Product := A.Reduce(1, function(X, Y: Double): Double begin Result := X * Y; end); WriteLn(Product); // => 120.0 // ( Reduce) Max := A.Reduce(function(X, Y: Double): Double begin if X > Y then Exit(X) else Exit(Y); end); WriteLn(Max); // => 5.0 end;
function TArrayHelper.Reduce(Init: Double; Lambda: TReduceRef): Double; var I: Integer; begin Result := Init; if Length(Self) = 0 then Exit; for I := 0 to High(Self) do Result := Lambda(Result, Self[I]); end; // Reduce – function TArrayHelper.Reduce(Lambda: TReduceRef): Double; var I: Integer; begin Result := Self[0]; if Length(Self) = 1 then Exit; for I := 1 to High(Self) do Result := Lambda(Result, Self[I]); end;
var A: TArray<Double>; Big: Double; begin A := [2, 3, 4]; // 2^(3^4). // Big := A.ReduceRight(function(Accumulator, Value: Double): Double begin Result := Math.Power(Value, Accumulator); end); Writeln(Big); // => 2.41785163922926E+0024 end;
function TArrayHelper.ReduceRight(Lambda: TReduceRef): Double; var I: Integer; begin Result := Self[High(Self)]; if Length(Self) = 1 then Exit; for I := High(Self) - 1 downto 0 do Result := Lambda(Result, Self[I]); end;
// : . // ( ) // , reference- function Sum(X, Y: Double): Double; begin Result := X + Y; end; // (Mean) (StdDev). procedure MeanAndStdDev; var Data: TArray<Double>; Mean, StdDev: Double; begin Data := [1, 1, 3, 5, 5]; Mean := Data.Reduce(Sum) / Length(Data); StdDev := Sqrt(Data .Map(function(V: Double): Double begin Result := Sqr(V - Mean); // end) .Reduce(Sum) / Pred(Length(Data))); WriteLn('Mean: ', Mean, ' StdDev: ', StdDev); // => Mean: 3.0 StdDev: 2.0 end;
Source: https://habr.com/ru/post/243721/
All Articles