# Dictionary {#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.

|Function|Regular Dictionary|Ordered Oictionary|
|--------|------------------|------------------|
|Unary Function|scalar function|√|√|
|vector function \(regular and cum/m functions\)|√|√|
|aggregate function|√|√|
|Binary Function|scalar function|√ \(The other parameter can only take a dictionary or a scalar.\)|√|
|vector function \(regular and cum/m functions\)|√ \(The other parameter can only take a dictionary or a scalar.\)|√|
|aggregate function|√|√|

For non-vector functions, the dictionary is always processed row by row: elements at the same position across all keys are combined into a row, and the function is applied row by row.

For vector functions, the dictionary can be processed either row by row or column by column, controlled by the *processVectorFunctionOverTupleByRow* parameter:

-   true \(default\): row-wise. Elements at the same position across all keys are combined into a row, and the function is applied row by row.
-   false: column-wise. Each value vector is treated as a column, and the function is applied separately to each column.

**Parent topic:**[Data Forms](../../../Programming/DataTypesandStructures/DataForms/DataForms.md)

## Creating Dictionaries {#creating-dictionaries}

To create dictionaries, we can use [dict](../../../Functions/d/dict.md) or [syncDict](../../../Functions/s/syncDict.md) 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](../../../Functions/d/dict.md) \(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 {#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](../../../Functions/f/find.md) 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 {#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!](../../../Functions/d/dictUpdate!.md).

```
// 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!](../../../Functions/e/erase!.md); Clear all keys using function [clear!](../../../Functions/c/clear!.md).

```
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 {#searching-dictionaries}

We can use function [in](../../../Functions/i/in.md) 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 {#topic_f4s_kxg_d2c}

### Converting a Dictionariy to a table {#topic_tmz_kxg_d2c}

You can transpose a dictionary into a table using the `transpose` function. For more conversion rules, refer to the[function page](../../../Functions/t/transpose.md).

Transposing a flat dictionary to a table:

``` {#codeblock_rxf_4xg_d2c}
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:

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

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

<table id="table_zv2_1xg_d2c"><thead><tr><th align="left">

key

</th><th align="left">

val1

</th><th align="left">

val2

</th></tr></thead><tbody><tr><td align="left">

tag1

</td><td align="left">

2

</td><td align="left">

6

</td></tr><tr><td align="left">

tag2

</td><td align="left">



</td><td align="left">

1

</td></tr></tbody>
</table>### Merging Multiple Dictionaries into a Table {#topic_cd1_lxg_d2c}

The higher-order function [each](../../../Functions/Templates/each.md) combined with the [asis](../../../Functions/a/asis.md) 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.

``` {#codeblock_rkn_wxg_d2c}
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 {#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.


