Overview
The BI.Arrays unit provides dynamic array types and powerful helper methods for working with data in TeeBI. These arrays form the foundation of TDataItem’s storage mechanism and include extensive functionality for sorting, searching, statistical calculations, and data manipulation.
Array Types
Dynamic array of 32-bit integers.var
Numbers: TInt32Array;
begin
Numbers.Resize(5);
Numbers[0] := 10;
Numbers[1] := 20;
end;
Dynamic array of 64-bit integers.
Dynamic array of single-precision floating-point numbers.
Dynamic array of double-precision floating-point numbers (default float type).
Dynamic array of extended-precision floats (10 bytes on x86, same as Double on x64).
Dynamic array of strings.
Dynamic array of datetime values.
Dynamic array of boolean values.
TNativeIntArray
TInt32Array or TInt64Array
Platform-dependent integer array (32-bit on x86, 64-bit on x64).
Common Helper Methods
All array types provide similar helper methods through record helpers. Below are the most commonly used methods:
Array Management
Returns the number of elements in the array.ShowMessage('Elements: ' + IntToStr(Numbers.Count));
Changes the size of the array.Numbers.Resize(100); // Resize to 100 elements
Clears all elements from the array (sets length to 0).
Adds a value to the end of the array.The value to append (type matches array type)
Returns the index of the newly added element.var Index: Integer;
Index := Numbers.Append(42);
Creates a copy of the array or a portion of it.Starting index for partial copy
Number of elements to copy
var Copy1, Copy2: TInt32Array;
Copy1 := Numbers.Copy; // Full copy
Copy2 := Numbers.Copy(10, 5); // Copy 5 elements starting at index 10
Inserts a value at the specified position.Numbers.Insert(5, 99); // Insert 99 at position 5
Removes one or more elements from the array.Number of elements to delete
Numbers.Delete(10); // Delete element at index 10
Numbers.Delete(5, 3); // Delete 3 elements starting at index 5
Reverses the order of elements in the array.
Swaps two elements in the array.Numbers.Swap(0, 5); // Swap first and sixth elements
Sorting and Searching
Sorts the array in ascending or descending order.For text arrays, whether to ignore case
Numbers.Sort; // Sort ascending
Numbers.Sort(False); // Sort descending
Text.Sort(True, True); // Sort text case-insensitive
Performs binary search on a sorted array.Returns True if value was found
Returns the index where the value is or should be inserted.var
Index: Integer;
Found: Boolean;
begin
Numbers.Sort; // Must be sorted first
Index := Numbers.SortedFind(42, Found);
if Found then
ShowMessage('Found at index: ' + IntToStr(Index));
end;
Finds the first occurrence of a value (linear search).Returns the index of the value, or -1 if not found.var Index: Integer;
Index := Numbers.IndexOf(42);
if Index >= 0 then
ShowMessage('Found at: ' + IntToStr(Index));
Statistical Methods (Numeric Arrays)
Calculates comprehensive statistics for the array.Returns a statistics object (TInt32Stats, TDoubleStats, etc.) containing:
- Min, Max: Minimum and maximum values
- Mean: Average value
- Median: Middle value
- Mode: Most frequent value
- Range: Difference between max and min
- Variance: Statistical variance
- StdDeviation: Standard deviation
- Skewness: Distribution skewness
- Peakedness: Distribution kurtosis
var S: TInt32Stats;
S := Numbers.Stats;
ShowMessage('Mean: ' + FloatToStr(S.Mean));
ShowMessage('Min: ' + IntToStr(S.Min));
ShowMessage('Max: ' + IntToStr(S.Max));
S.Free;
Calculates the sum of all values.ShowMessage('Total: ' + FloatToStr(Numbers.Sum));
Calculates the average value.ShowMessage('Average: ' + FloatToStr(Numbers.Mean));
Returns the minimum value in the array.ShowMessage('Min: ' + IntToStr(Numbers.Minimum));
Returns the maximum value in the array.ShowMessage('Max: ' + IntToStr(Numbers.Maximum));
Calculates variance given a mean.var M, V: Double;
M := Numbers.Mean;
V := Numbers.Variance(M);
Calculates standard deviation given a mean.var M, SD: Double;
M := Numbers.Mean;
SD := Numbers.StdDeviation(M);
Usage Examples
Basic Array Operations
var
Numbers: TInt32Array;
I: Integer;
begin
// Create and populate
Numbers.Resize(5);
Numbers[0] := 10;
Numbers[1] := 30;
Numbers[2] := 20;
Numbers[3] := 50;
Numbers[4] := 40;
// Append more values
Numbers.Append(60);
Numbers.Append(15);
ShowMessage('Count: ' + IntToStr(Numbers.Count)); // 7
// Sort
Numbers.Sort;
// Display sorted
for I := 0 to Numbers.Count - 1 do
ShowMessage(IntToStr(Numbers[I]));
// Shows: 10, 15, 20, 30, 40, 50, 60
end;
Statistical Analysis
var
Values: TDoubleArray;
Stats: TDoubleStats;
begin
// Populate with data
Values.Resize(100);
for var I := 0 to 99 do
Values[I] := Random * 100;
// Calculate statistics
Stats := Values.Stats;
try
ShowMessage('Count: ' + IntToStr(Values.Count));
ShowMessage('Mean: ' + FloatToStr(Stats.Mean));
ShowMessage('Median: ' + FloatToStr(Stats.Median));
ShowMessage('Min: ' + FloatToStr(Stats.Min));
ShowMessage('Max: ' + FloatToStr(Stats.Max));
ShowMessage('Range: ' + FloatToStr(Stats.Range));
ShowMessage('StdDev: ' + FloatToStr(Stats.StdDeviation));
finally
Stats.Free;
end;
end;
Text Array Operations
var
Names: TTextArray;
Index: Integer;
Found: Boolean;
begin
// Add names
Names.Append('Alice');
Names.Append('Bob');
Names.Append('Charlie');
Names.Append('David');
// Sort alphabetically (case-insensitive)
Names.Sort(True, True);
// Search
Index := Names.SortedFind('charlie', Found, True);
if Found then
ShowMessage('Found at index: ' + IntToStr(Index));
// Insert in sorted position
Names.Insert(Index, 'Carlos');
end;
Copying and Filtering
var
Source, Filtered: TInt32Array;
I: Integer;
begin
// Create source array
Source.Resize(10);
for I := 0 to 9 do
Source[I] := I * 10; // 0, 10, 20, ..., 90
// Filter: copy only values > 40
for I := 0 to Source.Count - 1 do
if Source[I] > 40 then
Filtered.Append(Source[I]);
ShowMessage('Filtered count: ' + IntToStr(Filtered.Count));
// Shows: 5 (values 50, 60, 70, 80, 90)
end;
DateTime Array
var
Dates: TDateTimeArray;
Stats: TDateTimeStats;
begin
// Add dates
Dates.Append(EncodeDate(2024, 1, 15));
Dates.Append(EncodeDate(2024, 3, 20));
Dates.Append(EncodeDate(2024, 2, 10));
Dates.Append(EncodeDate(2024, 4, 5));
// Sort chronologically
Dates.Sort;
// Get statistics
Stats := Dates.Stats;
try
ShowMessage('Earliest: ' + DateToStr(Stats.Min));
ShowMessage('Latest: ' + DateToStr(Stats.Max));
ShowMessage('Median: ' + DateToStr(Stats.Median));
finally
Stats.Free;
end;
end;
Working with Missing Values
var
Values: TDoubleArray;
Missing: TBooleanArray;
Filtered: TDoubleArray;
I: Integer;
begin
// Create arrays
Values.Resize(5);
Missing.Resize(5);
Values[0] := 10.0;
Missing[0] := False;
Values[1] := 0.0;
Missing[1] := True; // Missing
Values[2] := 20.0;
Missing[2] := False;
Values[3] := 0.0;
Missing[3] := True; // Missing
Values[4] := 30.0;
Missing[4] := False;
// Copy only non-missing values
Filtered := Values.Copy(Missing);
ShowMessage('Valid values: ' + IntToStr(Filtered.Count));
// Shows: 3
ShowMessage('Average: ' + FloatToStr(Filtered.Mean));
// Shows: 20.0 (average of 10, 20, 30)
end;
Advanced: Custom Sort with Callback
type
TPerson = record
Name: String;
Age: Integer;
end;
TPersonArray = array of TPerson;
var
People: TPersonArray;
Ages: TInt32Array;
procedure SwapPeople(const A, B: TInteger);
var
Temp: TPerson;
begin
Temp := People[A];
People[A] := People[B];
People[B] := Temp;
end;
begin
// Create people array
SetLength(People, 3);
People[0].Name := 'Alice'; People[0].Age := 30;
People[1].Name := 'Bob'; People[1].Age := 25;
People[2].Name := 'Carol'; People[2].Age := 35;
// Extract ages for sorting
Ages.Resize(3);
Ages[0] := People[0].Age;
Ages[1] := People[1].Age;
Ages[2] := People[2].Age;
// Sort ages and swap people accordingly
Ages.Sort(True, SwapPeople);
// Now People array is sorted by age
for var I := 0 to High(People) do
ShowMessage(People[I].Name + ': ' + IntToStr(People[I].Age));
// Shows: Bob: 25, Alice: 30, Carol: 35
end;
Pre-allocate with Resize: Use Resize to allocate memory once rather than calling Append repeatedly for large datasets.
Binary Search: Always use SortedFind on sorted arrays instead of IndexOf for O(log n) instead of O(n) search time.
In-place Operations: Methods like Sort, Reverse, and Initialize work in-place without allocating new memory.
Copy Overhead: Copy creates a new array; avoid unnecessary copies for large datasets.
See Also
- TDataItem - Uses these arrays for data storage
- TDataKind - Determines which array type is used
- TMissingData - Uses TBooleanArray for tracking missing values