Collections: List and Dictionary
ToolBox supports the generic collection types List of [Type] and Dictionary of [KeyType, ValueType]. Unlike arrays, collections grow and shrink dynamically, and you iterate them with the foreach statement.
List of [Type]
A List is an ordered, dynamically sized collection of elements of one type. Lists are 1-based: the first element is at index 1.
Declaration
var
Names: List of [Text];
Amounts: List of [Decimal];
Numbers: List of [Integer];
Tokens: List of [JsonToken];
The element type can be any scalar type (Text, Code, Integer, BigInteger, Decimal, Boolean, Date, Time, DateTime, Duration, Guid, Char, Byte, Option, ...) or one of the four JSON types. Record, Dialog, and nested collections (List of [List of [Text]]) are not allowed as elements. A size on the element type (List of [Text[50]]) is accepted but not enforced.
Members
| Member | Returns | Description |
|---|---|---|
add(Value) |
Append an element | |
count() |
Integer | Number of elements |
contains(Value) |
Boolean | Whether the value is present |
get(Index) |
element | 1-based; errors when out of range |
get(Index, var Value) |
1-based; fills the variable | |
getrange(Index, Count) |
List | 1-based sublist |
indexof(Value) |
Integer | 1-based position; 0 when not found |
lastindexof(Value) |
Integer | 1-based position of the last match; 0 when none |
insert(Index, Value) |
1-based insert | |
remove(Value) |
Boolean | Removes the first occurrence |
removeat(Index) |
1-based remove | |
set(Index, Value) |
1-based; replace an element | |
reverse() |
Reverse the list in place | |
addrange(FromList) |
Append all elements of another list |
Example
var
Fruits: List of [Text];
Fruit: Text;
First: Text;
begin
Fruits.Add('Apple');
Fruits.Add('Banana');
Fruits.Add('Cherry');
Message('Count: %1', Fruits.Count()); // 3
Message('Position of Banana: %1', Fruits.IndexOf('Banana')); // 2
Fruits.Get(1, First);
Message('First: %1', First); // Apple
Fruits.Reverse();
foreach Fruit in Fruits do
Message('Fruit: %1', Fruit); // Cherry, Banana, Apple
end;
Dictionary of [KeyType, ValueType]
A Dictionary maps keys to values. Each key is unique. Keys are matched by their text- formatted value, so two keys that format to the same text are considered the same key.
Declaration
var
Prices: Dictionary of [Text, Decimal];
Counts: Dictionary of [Code, Integer];
The key type must be one of Text, Code, Integer, BigInteger, Option, Boolean, Guid, Date, Time, DateTime, or Decimal. The value type follows the same rules as a List element type (any scalar or JSON type; no records, dialogs, or nested collections).
Members
| Member | Returns | Description |
|---|---|---|
add(Key, Value) |
Errors when the key already exists | |
set(Key, Value) |
Add or replace | |
containskey(Key) |
Boolean | Whether the key is present |
count() |
Integer | Number of entries |
get(Key) |
value | Errors when the key is missing |
get(Key, var Value) |
Fills the variable | |
remove(Key) |
Boolean | Removes the entry |
keys() |
List | All keys as a list |
values() |
List | All values as a list |
Example
var
Stock: Dictionary of [Text, Integer];
ItemNo: Text;
Qty: Integer;
Keys: List of [Text];
begin
Stock.Add('1000', 25);
Stock.Add('1100', 40);
Stock.Set('1000', 30); // replace existing value
if Stock.ContainsKey('1100') then
Message('1100 stock: %1', Stock.Get('1100'));
Keys := Stock.Keys();
foreach ItemNo in Keys do begin
Stock.Get(ItemNo, Qty);
Message('Item %1: %2 in stock', ItemNo, Qty);
end;
end;
Iterating with foreach
The foreach statement iterates over a List (and over the results of methods such as Text.Split(), Dictionary.Keys(), Dictionary.Values(), and Regex.Split() that return a list), and over a JsonArray with a JsonToken loop variable.
Syntax
foreach <element> in <collection> do
<statement>;
The loop variable's type must match the collection's element type. A Dictionary itself cannot be the subject of foreach; iterate its Keys() or Values() list instead.
var
Csv: Text;
Parts: List of [Text];
Part: Text;
begin
Csv := 'red,green,blue';
Parts := Csv.Split(','); // Text.Split returns a List of [Text]
foreach Part in Parts do
Message('Color: %1', Part);
end;
Split must be called on a Text variable; a string literal cannot be the receiver of a method call (see Text Methods).
inas a keyword:foreach ... in ...usesinas part of the loop syntax. The sameinword is also the set-membership operator (if X in [1, 3..5] then). ToolBox distinguishes them by context, soinis not otherwise reserved. See Control Flow.
Differences from Standard AL
- Lists are 1-based in ToolBox, matching AL. (Note that JSON arrays are 0-based — see
- Dictionary keys are compared by their text-formatted value. This makes
CodeandText
keys interoperate naturally but means numerically-distinct keys that format identically collide.
foreachover a Dictionary is not supported. Standard AL iterates the keys; in ToolBox
you iterate Keys() or Values() explicitly.
- Lists and dictionaries are reference types, as in standard AL: assigning one variable to
another or passing it to a procedure shares the same collection. Clear(MyList) rebinds the variable to a new, empty collection.