1D Arrays Grade 11

Imagine you need to store 30 student marks. Without arrays you would need 30 separate variables — iMark1, iMark2, … iMark30. With an array, one name stores them all: arrMarks[1..30]. Arrays are a Grade 11 Term 1 topic.

T1Term 1 · 1D Arrays & Array Algorithms

Why Use Arrays?

Without Arrays var iMark1, iMark2, iMark3, iMark4, iMark5, iMark6, iMark7, iMark8, iMark9, iMark10, iMark11, iMark12, iMark13, iMark14, iMark15, iMark16, iMark17, iMark18, iMark19, iMark20, iMark21, iMark22, iMark23, iMark24, iMark25, iMark26, iMark27, iMark28, iMark29, iMark30 : Integer; 30 separate variables — hard to loop over! With Arrays var arrMarks : array[1..30] of Integer; // Loop through all 30 with 3 lines: for i := 1 to 30 do iTotal := iTotal + arrMarks[i]; One name, 30 values, loops work perfectly!

What is a 1D Array?

A one-dimensional array is a structured data type that stores a fixed number of values of the same data type under a single variable name, with each individual value accessed using its own index (a whole number giving that value's position in the list).

ANALOGY — an array is a dinner set

Think of an array like a train: each carriage (box) holds one value and is numbered by its index — the index tells you exactly where to find that value.

Remember a single variable is one cup. An array is a whole matching dinner set — say 6 cups — that all share one name and are numbered: arrCups[1], arrCups[2]arrCups[6]. Every item is the same type (all cups), just at a different index (place-setting number).

So instead of naming 30 separate cups cup1, cup2, …, you keep one name and pick the one you want by its number: arrMarks[7] is simply "the mark at place setting 7".

arrNames : array[1..7] of String Index [1] Index [2] Index [3] Index [4] Index [5] Index [6] Index [7] 'Alice' 'Bob' 'Callie' 'David' 'Eve' 'Farai' 'Gio' arrNames[3] = 'Callie' · arrNames[1] = 'Alice' · To access last: arrNames[7]

Declaring an Array

Syntax
arrName : array [lowerIndex..upperIndex] of DataType;
Examples
var
  arrNames  : array [1..30] of String;
  arrMarks  : array [1..30] of Integer;
  arrPrices : array [0..9]  of Real;

Arrays of Unknown Length — use a constant

You don't always know in advance exactly how many items you will store. A common trick is to declare a constant for the maximum size, then use it as the upper index. If the size needs to change later, you only edit one line.

Declare the constant BEFORE the array

The constant must be declared above the array declaration (it can go just above type in the interface section), otherwise Delphi won't know what Max means yet.

Delphi
const
  Max = 100;                          // maximum possible learners
var
  arrNames : array [1..Max] of String;
  iCount   : Integer;                  // how many are ACTUALLY used

Keep a separate counter (iCount) for how many elements are really in use, and loop 1 to iCount instead of 1 to Max.

Dynamic Arrays

A dynamic array has no fixed size when declared — you set (and can later change) its length while the program runs with SetLength. This is perfect when the number of items is only known at runtime (e.g. after reading a file).

Dynamic arrays start at index 0

Unlike array[1..30], a dynamic array is always 0-based. If you SetLength(arr, 5) the valid indexes are 0,1,2,3,4. Use Low(arr) for the first index (0) and High(arr) for the last (length − 1).

RoutinePurpose
SetLength(arr, n)Sets (or changes) the array to hold n elements
Length(arr)Returns the current number of elements
Low(arr)First valid index (always 0 for dynamic arrays)
High(arr)Last valid index (Length − 1)
Delphi — dynamic array
var
  arrNum : array of Integer;   // note: NO index range given
  i : Integer;
begin
  SetLength(arrNum, 5);          // now holds 5 ints, index 0..4

  for i := Low(arrNum) to High(arrNum) do
    arrNum[i] := i * 2;           // 0, 2, 4, 6, 8

  SetLength(arrNum, 8);          // grow to 8 — existing values are kept
end;

Populating an Array

Method 1: Fixed values

Delphi
arrNames[1] := 'Alice';
arrNames[2] := 'Bob';
arrNames[3] := 'Callie';

Method 2: Constant array (known at compile time)

Delphi
const
  arrDays : array [1..7] of String =
    ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');

Method 3: User input with a loop

Delphi
for i := 1 to 30 do
  arrNames[i] := InputBox('Name', 'Enter name:', '');

Displaying & Calculating

Delphi
// Display all
for i := 1 to Length(arrMarks) do
  memOut.Lines.Add(IntToStr(arrMarks[i]));

// Sum and average
iTotal := 0;
for i := 1 to Length(arrMarks) do
  iTotal := iTotal + arrMarks[i];
rAvg := iTotal / Length(arrMarks);

Shortcut: the Math Unit

Writing your own loop to total or average an array works, but Delphi's Math unit already has ready-made functions that do the same job in one line.

FunctionReturns
Sum(arr)Total of every element
Mean(arr)Average of every element
MaxValue(arr)The largest value in the array
MinValue(arr)The smallest value in the array
Delphi — Math unit shortcuts
uses Math;   // add this to the uses clause first

rAvg     := Mean(arrPrices);
rTotal   := Sum(arrPrices);
rHighest := MaxValue(arrPrices);
rLowest  := MinValue(arrPrices);
Only for arrays of type Double

These four functions only accept an array whose elements are declared as Double — not Integer, and not the general-purpose Real. If your array holds integers, either redeclare it as array[1..n] of Double, or stick to your own loop.

Arrays with Meaningful Indices

Every index used so far has just meant "the Nth item in the list" — arrNames[3] is simply whoever happens to be third. Sometimes, though, it's more useful to let the index itself carry meaning. If arrVotes[4] always holds the vote count for competitor number 4, the index is the competitor number, not just a position in a queue.

Using a Char as the Index

An index isn't limited to whole numbers — any ordinal type can be used, including Char. This is handy whenever the letter itself is what you want to look values up by, e.g. tallying how many learners scored each grade symbol (A to F) in a test:

Delphi — a Char-indexed array
var
  arrSymbolCount : array ['A'..'F'] of Integer;
  cGrade : Char;
begin
  cGrade := 'A';
  while cGrade <= 'F' do
  begin
    arrSymbolCount[cGrade] := 0;   // reset every element to zero first
    cGrade := succ(cGrade);         // moves 'A' to 'B', 'B' to 'C', and so on
  end;

  // later, whenever a learner's symbol is worked out:
  Inc(arrSymbolCount[cLearnerSymbol]);
succ and pred

succ(cGrade) gives the character that comes after cGrade in the alphabet; pred(cGrade) gives the one before it. They work like +1/-1 for any ordinal type, including Char, where plain arithmetic isn't allowed.

Matching a RadioGroup's ItemIndex to an Array

A RadioGroup's ItemIndex always starts counting from 0 for its first button — but an array you declare yourself might start at 1. When you use ItemIndex to pick an element to update (for example, tallying votes for a menu option), you need to decide which convention your array follows and stay consistent:

Array declared [0..4]Array declared [1..5]
iChoice := rgpMenu.ItemIndex;
Inc(arrVotes[iChoice]);
iChoice := rgpMenu.ItemIndex + 1;
Inc(arrVotes[iChoice]);

With the [1..5] version, the array index is always one more than ItemIndex, because ItemIndex itself never moves off its 0-based counting — only your array's lower bound changes.

IndexOutOfBounds / range check error

Delphi will happily compile arrNames[50] even if arrNames was declared as [1..30] — the mistake only surfaces while the program is running, as a range-check/IndexOutOfBounds error the moment that line executes. Whenever an index comes from user input or from a component like ItemIndex, validate it against the array's real bounds before using it.

Linear Search

Delphi
bFound := False;
for i := 1 to Length(arrNames) do
  if arrNames[i] = sSearch then
  begin
    ShowMessage('Found at position ' + IntToStr(i));
    bFound := True;
    Break;
  end;
if not bFound then
  ShowMessage('Not found');
Pick the right search for the job

The code above stops the loop with Break as soon as one match turns up — correct when you only expect a single match (e.g. one learner's ID number). If instead you needed every occurrence (e.g. every learner who chose "Physics"), you would drop the flag and Break, and simply let the loop run to the end, adding each match found along the way. Once the array is sorted, binary search (below) beats both approaches for speed.

Binary Search (sorted array)

Binary search is much faster than linear — it halves the search range each step. The array must be sorted first. We are searching for 23 in the array [2, 5, 8, 12, 16, 23, 38, 56, 72, 91].

Binary Search — searching for 23 idx: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] val: 2 5 8 12 16 23 38 56 72 91 Step iLow iHigh iMid arrNums[iMid] 1 1 10 5 (1+10) div 2 16 < 23 → iLow = 6 2 6 10 8 (6+10) div 2 56 > 23 → iHigh = 7 3 6 7 6 (6+7) div 2 23 = 23 → FOUND! Found 23 at position 6 in just 3 steps! Linear search would have taken 6 steps. iLow := 1; iHigh := Length(arrNums); bFound := False; while (iLow <= iHigh) and not bFound do begin iMid := (iLow + iHigh) div 2; if arrNums[iMid] = iTarget then bFound := True
Delphi — binary search
iLow := 1;
iHigh := Length(arrNums);
bFound := False;
while (iLow <= iHigh) and not bFound do
begin
  iMid := (iLow + iHigh) div 2;
  if arrNums[iMid] = iTarget then
    bFound := True
  else if arrNums[iMid] < iTarget then
    iLow := iMid + 1
  else
    iHigh := iMid - 1;
end;
if bFound then
  ShowMessage('Found at position ' + IntToStr(iMid));

How String Comparison Works

Sorting a string array with > and < only makes sense once you know what Delphi is actually comparing. It never looks at "the alphabet" directly — it walks each string letter by letter and compares the underlying ASCII value of each character, stopping at the first pair of letters that differ.

ComparisonResultWhy
'Alice' = 'alice'False'A' is ASCII 65, 'a' is ASCII 97 — string comparison is case-sensitive.
'Bob' < 'Eve'TrueFirst letters differ straight away: 'B' (66) is less than 'E' (69).
'Farai' < 'Farm'TrueThe first three letters ('F','a','r') match, so the 4th letter decides: 'a' (97) is less than 'm' (109).
'Gio' > 'Gi'TrueDelphi pads the shorter string with trailing spaces to compare them — so 'Gi' becomes 'Gi ', and 'o' (111) beats a space (32).
Capitals sort before lowercase

Because every uppercase letter has a lower ASCII value than every lowercase letter, an unsorted mix of cases will group all the capitalised words before any lowercase word once sorted — not what most people expect from "alphabetical order". If that matters, convert both sides to the same case (e.g. with UpperCase()) before comparing or sorting.

Bubble Sort — Pass by Pass

Bubble sort compares adjacent elements and swaps them if they are in the wrong order. After each full pass, the largest unsorted value "bubbles" to its correct position at the end. Array: [5, 3, 8, 1, 9] — sorting ascending.

Bubble Sort — [5, 3, 8, 1, 9] Start Pass 1 Pass 2 Pass 3 Pass 4 Sorted 5 3 8 1 9 3 5 1 8 9 9 locked in 3 1 5 8 9 8, 9 locked 1 3 5 8 9 1 3 5 8 9 1 3 5 8 9 violet = swapped this pass green = locked in final position
Delphi — Bubble Sort
for i := Length(arrNums) - 1 downto 1 do
  for j := 1 to i do
    if arrNums[j] > arrNums[j + 1] then
    begin
      iTemp := arrNums[j];
      arrNums[j] := arrNums[j + 1];
      arrNums[j + 1] := iTemp;
    end;
Stop early once nothing swaps

The version above always completes every single pass, even once the array is already sorted. A smarter bubble sort keeps a Boolean flag and quits the moment a whole pass goes by with no swaps at all — because that can only happen when the array is fully sorted:

Delphi — Bubble Sort that quits early
iEndCounter := Length(arrNums) - 1;
repeat
  bSwapped := False;
  for j := 1 to iEndCounter do
    if arrNums[j] > arrNums[j + 1] then
    begin
      iTemp := arrNums[j];
      arrNums[j] := arrNums[j + 1];
      arrNums[j + 1] := iTemp;
      bSwapped := True;
    end;
  Dec(iEndCounter);            // the tail end is sorted, so search one less item next time
until not bSwapped;         // no swaps this pass = fully sorted, stop looping

Selection Sort — Pass by Pass

Selection sort finds the smallest remaining element and swaps it into its correct position. Same array: [5, 3, 8, 1, 9].

Selection Sort — [5, 3, 8, 1, 9] Start Pass 1 Pass 2 Pass 3 Pass 4 5 3 8 1 9 1 3 8 5 9 min=1 found at [4], swap → [1] locked 1 3 8 5 9 min=3 already at [2] — locked 1 3 5 8 9 min=5 found at [4], swap → [3] locked 1 3 5 8 9 SORTED!
Delphi — Selection Sort
for i := 1 to Length(arrNums) - 1 do
begin
  iMin := i;
  for j := i + 1 to Length(arrNums) do
    if arrNums[j] < arrNums[iMin] then
      iMin := j;
  if iMin <> i then
  begin
    iTemp := arrNums[i];
    arrNums[i] := arrNums[iMin];
    arrNums[iMin] := iTemp;
  end;
end;

Parallel Arrays

Two arrays are parallel when the same index refers to the same "record" — e.g. arrNames[3] and arrMarks[3] both belong to the same student. When you sort one, you must sort both to keep them in sync.

ANALOGY — your things move with you

At a table, each person has their own cup, plate and bowl — three parallel dinner sets, where place setting [3] in each belongs to the same person. If that person moves to a different seat, they take all three of their things with them — you never leave their cup behind while their plate moves.

Sorting parallel arrays works exactly the same way: whenever the sort swaps two items in arrNames, you must swap the same two indexes in arrMarks (and every other parallel array) — so each student keeps their own name and their own mark together.

Parallel Arrays — Same Index, Different Data arrNames 'Alice' 'Bob' 'Callie' 'David' 'Eve' [1] [2] [3] [4] [5] arrMarks 78 65 91 54 88 arrNames[3] = 'Callie' linked to arrMarks[3] = 91 — same student, same index
Delphi — parallel sort (names & marks together)
for i := 1 to Length(arrNames) - 1 do
  for j := i + 1 to Length(arrNames) do
    if arrNames[i] > arrNames[j] then
    begin
      // Swap both arrays at the same time
      sTemp := arrNames[i]; arrNames[i] := arrNames[j]; arrNames[j] := sTemp;
      iTemp := arrMarks[i]; arrMarks[i] := arrMarks[j]; arrMarks[j] := iTemp;
    end;

Date Methods (Grade 11)

Delphi has built-in functions for working with dates — required for Grade 11 Term 1.

Add this to your uses clause

IsLeapYear, YearOf, MonthOf and DayOf live in the DateUtils unit. Add uses DateUtils; near the top of your unit, or Delphi will report "undeclared identifier" when you try to use them.

FunctionReturnsExample & Output
NowCurrent date & time (TDateTime)lblDate.Caption := DateToStr(Now)'2025/05/30'
DateToStr(d)Date as formatted stringDateToStr(dtpBirth.Date)'2008/03/15'
TimeToStr(t)Time as formatted stringTimeToStr(Now)'14:32:07'
StrToDate(s)String → TDateTimeStrToDate('2024/05/01')
IsLeapYear(y)Boolean (True/False)IsLeapYear(2024)True
YearOf(d)Integer yearYearOf(dtpDate.Date)2025
MonthOf(d)Integer month (1–12)MonthOf(Now)5
DayOf(d)Integer day (1–31)DayOf(Now)30
Delphi — Date examples with output
// Display today's date
lblToday.Caption := DateToStr(Now);         // '2025/05/30'

// Calculate age in years
iAge := YearOf(Now) - YearOf(dtpBirth.Date); // e.g. 17

// Check leap year
if IsLeapYear(YearOf(Now)) then
  ShowMessage('This is a leap year')
else
  ShowMessage('Not a leap year');