Projections — Select / SelectMany
Projection operators transform elements from one type to another.
Select
Select<TResult> maps each element to a new value.
var LResult := TColligoArray<Integer>.From([1, 2, 3])
.Select<string>(function(const X: Integer): string
begin
Result := 'Item ' + IntToStr(X);
end)
.ToArray;
// Result: ['Item 1', 'Item 2', 'Item 3']
Select with index
An overload passes the element index as the second argument:
// function Select<TResult>(
// const ASelector: TFunc<T, Integer, TResult>): IColligoEnumerable<TResult>;
var LResult := TColligoArray<string>.From(['a', 'b', 'c'])
.Select<string>(function(const S: string; const Index: Integer): string
begin
Result := IntToStr(Index) + ':' + S;
end)
.ToArray;
// Result: ['0:a', '1:b', '2:c']
SelectMany
SelectMany<TResult> flattens a sequence of sequences (one-to-many projection).
type TOrder = record Lines: TArray<string>; end;
var LResult := TColligoArray<TOrder>.From(LOrders)
.SelectMany<string>(function(const O: TOrder): TArray<string>
begin
Result := O.Lines;
end)
.ToArray;
// Flat array of all order lines
SelectMany with collection selector and result selector
The two-selector overload first expands each source element into a sub-array (ACollectionSelector) and then combines each source element with each sub-element (AResultSelector):
// function SelectMany<TCollection, TResult>(
// const ACollectionSelector: TFunc<T, TArray<TCollection>>;
// const AResultSelector: TFunc<T, TCollection, TResult>): IColligoEnumerable<TResult>;
type
TOrder = record Id: Integer; Lines: TArray<string>; end;
TLineDetail = record OrderId: Integer; Line: string; end;
var LOrders: TArray<TOrder>;
// Assume LOrders is populated...
var LResult := TColligoArray<TOrder>.From(LOrders)
.SelectMany<string, TLineDetail>(
// expand: one order → its lines
function(const O: TOrder): TArray<string>
begin
Result := O.Lines;
end,
// combine: (order, line) → TLineDetail
function(const O: TOrder; const Line: string): TLineDetail
begin
Result.OrderId := O.Id;
Result.Line := Line;
end)
.ToArray;
// Flat array of TLineDetail, one per order line
Append / Prepend
Add a single element at the end or beginning of a sequence without modifying the original:
var LResult := TColligoArray<Integer>.From([2, 3])
.Prepend(1)
.Append(4)
.ToArray;
// Result: [1, 2, 3, 4]
Reverse
Reverse reverses the order of elements:
var LResult := TColligoArray<Integer>.From([1, 2, 3])
.Reverse
.ToArray;
// Result: [3, 2, 1]
DefaultIfEmpty
DefaultIfEmpty returns the sequence unchanged if it is non-empty, or a single default element if empty:
var LResult := TColligoArray<Integer>.From([])
.DefaultIfEmpty(0)
.ToArray;
// Result: [0]