Ast RTL: Map, Reduce, Where, Any

This commit is contained in:
Michael Schimmel
2025-09-18 16:09:51 +02:00
parent 1be9591a61
commit 5f110e4408
3 changed files with 233 additions and 51 deletions
+38
View File
@@ -254,6 +254,16 @@ type
property TotalCount: Int64 read GetTotalCount;
end;
TIndexSeries = class(TInterfacedObject, ISeries)
private
FIndexArray: TArray<Integer>;
function GetCount: Int64;
function GetTotalCount: Int64;
function GetItems(Idx: Integer): TScalar;
public
constructor Create(const AIndexArray: TArray<Integer>);
end;
TBinaryOperatorHelper = record helper for TBinaryOperator
function ToString: string;
end;
@@ -1557,6 +1567,34 @@ begin
Result := FTotalCount;
end;
{ TIndexSeries }
constructor TIndexSeries.Create(const AIndexArray: TArray<Integer>);
begin
inherited Create;
FIndexArray := AIndexArray;
end;
function TIndexSeries.GetCount: Int64;
begin
Result := Length(FIndexArray);
end;
function TIndexSeries.GetTotalCount: Int64;
begin
Result := GetCount;
end;
function TIndexSeries.GetItems(Idx: Integer): TScalar;
var
sourceIndex: Integer;
begin
// The series maintains the "0 is newest" convention.
// The index array was built from oldest to newest, so we access it in reverse.
sourceIndex := FIndexArray[GetCount - 1 - Idx];
Result := TScalar.FromInteger(sourceIndex);
end;
initialization
Assert(sizeof(TScalarValue) = 8);
+55 -1
View File
@@ -63,6 +63,8 @@ type
class function Defer(const Value: TDataValue; const Calc: TFunc): TDataValue; overload; static;
class function Map(const SourceSeries: ISeries; const MapperFunc: TFunc): ISeries; static;
class function FromRecordSeries(const AValue: IRecordSeries): TDataValue; static; inline;
class function FromRecord(const [ref] AValue: TScalarRecord): TDataValue; static; inline;
class function FromSeries(const AValue: ISeries): TDataValue; static; inline;
@@ -79,7 +81,6 @@ type
property Kind: TDataValueKind read GetKind;
end;
type
TDataValueKindHelper = record helper for TDataValueKind
public
function ToString: string;
@@ -112,6 +113,18 @@ type
constructor Create(const AVal: TScalar; const ACalc: TDataValue.TFunc);
end;
TMapSeries = class(TInterfacedObject, ISeries)
private
FSourceSeries: ISeries;
FMapperFunc: TDataValue.TFunc;
// ISeries
function GetCount: Int64;
function GetTotalCount: Int64;
function GetItems(Idx: Integer): TScalar;
public
constructor Create(const ASourceSeries: ISeries; const AMapperFunc: TDataValue.TFunc);
end;
constructor TManagedLazy.Create(AKind: TDataValueKind; const AVal: IInterface; const ACalc: TDataValue.TFunc);
begin
inherited Create;
@@ -329,6 +342,11 @@ begin
Result := TDataValueKind(FKind);
end;
class function TDataValue.Map(const SourceSeries: ISeries; const MapperFunc: TFunc): ISeries;
begin
Result := TMapSeries.Create(SourceSeries, MapperFunc);
end;
function TDataValue.ToString: String;
var
sb: TStringBuilder;
@@ -430,4 +448,40 @@ begin
end;
end;
{ TMapSeries }
constructor TMapSeries.Create(const ASourceSeries: ISeries; const AMapperFunc: TDataValue.TFunc);
begin
inherited Create;
FSourceSeries := ASourceSeries;
FMapperFunc := AMapperFunc;
end;
function TMapSeries.GetCount: Int64;
begin
Result := FSourceSeries.Count;
end;
function TMapSeries.GetTotalCount: Int64;
begin
Result := FSourceSeries.TotalCount;
end;
function TMapSeries.GetItems(Idx: Integer): TScalar;
var
sourceValue: TScalar;
argArray: TArray<TDataValue>;
mappedValue: TDataValue;
begin
// Get the original item, apply the mapper function, and return the result.
sourceValue := FSourceSeries.Items[Idx];
argArray := [TDataValue(sourceValue)];
mappedValue := FMapperFunc(argArray);
if mappedValue.Kind <> vkScalar then
raise EInvalidCast.Create('Map function did not return a scalar value.');
Result := mappedValue.AsScalar;
end;
end.