Dictionary

A dictionary is a container type that holds a list of unique key-value pairs. Dictionary keys must be a scalar in the following data categories: Integral (excluding COMPRESSED), Temporal, Floating and Literal. The values of a dictionary can be in any form and of any type.

A dictionary is mutable. The keys can be added and deleted, but not updated. The values can be updated.

There are two types of dictionaries. The regular dictionaries do not track the insertion order of the key-value pairs whereas the ordered dictionaries preserve the insertion order of key-value pairs. The dictionaries returned by built-in functions, such as the transpose of a table, the parse result of a JSON string, the output of a machine learning model, and the output of system performance metrics, are mostly ordered dictionaries.

The table below lists the function types that can work with dictionaries.

Dictionary Unary Function Binary Function Window Function Aggregate Function
regular dictionary √ (The other parameter can only take a dictionary or a scalar.) × ×
ordered dictionary × ×

Creating Dictionaries

To create dictionaries, we can use dict or syncDict where X is keys and Y is values. The parameter ordered specifies whether it is an ordered dictionary. Dictionaries created with syncDict support concurrent reads and writes by multiple threads.

x=1 2 3 1;
y=2.3 4.6 5.3 6.4;
z=dict(x, y);
// note the existence of duplicate keys of 1

z;
/* output
3->5.3
2->4.6
1->6.4
*/
// when there are duplicate keys, the value is set as the last update.


z=dict(y, x);
z;
/* output
6.4->1
5.3->3
4.6->2
2.3->1
*/

$z=dict(y,x,true)
$z;
2.3->1
4.6->2
5.3->3
6.4->1
// ordered dictionary

We can also create an empty dictionary with with specified data types for the keys and values, then insert (key, value) pairs into the dictionary.


/ create an empty dictionary with integer as keyType and double as valueType.

 z=dict(int,double);


/ insert a new (key, value) pair

 z[1]=7.9;

 z;

->7.9

// update a value

 z[1]=6.3;

 z;

->6.3;


 z[-1]=1000;

;

1->1000

->6.3```

To create a dictionary that can contain all types of values, we can use dict(string,any) dict (string, any)

z=dict(string,any)
z[`IBM]=172.91 173.45 171.6
z[`MS]=29.11 29.03 29.4
z[`SECOND]=10:30:01s 10:30:03s 10:30:05s
z[`TOTAL]=3
z;

/* output
SECOND->[10:30:01,10:30:03,10:30:05]
MS->[29.11,29.03,29.4]
TOTAL->3
IBM->[172.91,173.45,171.6]
*/

Accessing Dictionaries

x=3 6 1 5 9
y=4.2 3.7 8.8 6.4 5.3
z=dict(x, y)
z;

/* output
9->5.3
5->6.4
1->8.8
6->3.7
3->4.2
*/

keys z;
// output: [9,5,1,6,3]
// get all the keys of a dictionary

values z;
// output: [5.3,6.4,8.8,3.7,4.2]
// get all the values of a dictionary

size z;
// output: 5

z[9];
// output: 5.3

z[5 3];
// output: [6.4,4.2]

z.3;
// output: 4.2;

z.(3 5);
// output: [4.2,6.4]

x=dict(`IBM`GOOG`MSFT, (1 2 3, 4 5 6, 7 8 9));
x;
/* output
MSFT->[7,8,9]
IBM->[1,2,3]
GOOG->[4,5,6]
*/

x[`IBM`MSFT];
// output: ([1,2,3],[7,8,9])

x[`IBM`MSFT,1 2];
// output: ([2,3],[8,9])

We can also use the function find to get values from a dictionary with specified keys:

find(z,1 3);
// output: [8.8,4.2]

z find 5;
// output: 6.4

find(z, 7 3);
// output: [,4.2]
// 7 is not a key in the dictionary, so it returns NULL.

Modifying Dictionaries

We can update or append a dictionary with statement Z[X]=Y. If the key exists in the dictionary, the statement updates the value; otherwise it adds a new key-value pair to dictionary Z. Another way to update a dictionary is to use function dictUpdate!.

// update the dictionary z
z[1]=9.2
z[3 5]=4.3 6.5
z;

/* output
9->5.3
5->6.5
1->9.2
6->3.7
3->4.3
*/

// append new key value pairs to z
z[2]=5
z;

/* output
2->5
9->5.3
5->6.5
1->9.2
6->3.7
3->4.3
*/

// the statement below fails as z.2 has ready only access to the value of the key 2.
z.2=5;
// output: Syntax Error: [line #1] Please use '==' rather than '=' as equal operator in non-sql expression.

// update dictioncary with dictUpdate!
x=dict(1 2 3, 1 1 1);
x;
/* output
3->1
1->1
2->1
*/

dictUpdate!(x, add, 2 3, 1 2);
/* output
3->3
1->1
2->2
*/

x.dictUpdate!(mul, 3 4, 2 4);
/* output
4->4
3->6
1->1
2->2
*/

Erasing a key using function erase!; Clear all keys using function clear!.

x=1..3
y=4..6
z=dict(x,y);

z;
/* output
3->6
1->4
2->5
*/

z.erase!(3);
/* output
1->4
2->5
*/

z.clear!();

z;

Binary operations on an ordered dictionary and an array of the same size are supported. The result is a dictionary where the keys are unchanged and the values are calculation results between the original dictionary values and the array.

x=`a `b `c `d;
y=2.3 4.6 5.3 6.1;
z=dict(x, y,true);
x = 1 1 1 1

/* output
$z+x;
a->3.3
b->5.6
c->6.3
d->7.1
*/

Searching Dictionaries

We can use function in to search if a dictionary contains certain keys.

x=1..3
y=4..6
z=dict(x,y);

1 in z;
// output: 1

10 in z;
// output: 0

Converting Dictionaries to a Table

Converting a Dictionariy to a table

You can transpose a dictionary into a table using the transpose function. For more conversion rules, refer to the function page.

Transposing a flat dictionary to a table:

d=dict(`sym`val,[`a`b`c,1 2 3]);
d;
/*
val->[1,2,3]
sym->[a,b,c]
*/
transpose(d);
val sym
1 a
2 b
3 c

Transposing a nested dictionary to a table:

d = {'tag1':{'val1':2,'val2':6},'tag2':{'val2':1, 'val3':3}}
d
/*
tag1->
    val1->2
    val2->6

tag2->
    val2->1
    val3->3
*/
transpose(d)

key

val1

val2

tag1 2 6
tag2 1

Merging Multiple Dictionaries into a Table

The higher-order function each combined with the asis function can be used to merge multiple dictionaries into a table.

The schema of merged table is determined by the first dictionary, where the column names correspond to the keys of that dictionary. The data for each row comes from the corresponding value of the key in the dictionaries. If a key is missing in a dictionary, the corresponding value in the table will be NULL.

In the example, the merged table will have columns key1, key2, key3, and key4 from d1. Since d2 does not contain key1, the corresponding value in the merged table will be NULL.

d1 = {'key1':10,'key2':"A1",'key3':0.15,'key4':[1,2,3]}
d1
/*
key1->10
key2->A1
key3->0.15
key4->[1,2,3]
*/

d2 = {'key2':"B1",'key3':0.16,'key4':[2,4,6,8],'key5':12}
d2
/*
key2->B1
key3->0.16
key4->[2,4,6,8]
key5->12
*/

asis:E([d1,d2])
key1 key2 key3 key4
10 A1 0.15 [1, 2, 3]
B1 0.16 [2, 4, 6, 8]

Performance Notes

  • Integer keys are preferred for optimal performance.

  • Vector-based operations are preferred such as accessing a dictionary with a vector.

  • Retrieval of all keys or values scans the entire dictionary.

  • If you need to frequently delete elements from a dictionary, ordered dictionaries should be avoided as the performance would be slower than using regular dictionaries.