How to Work with Dictionaries
This page provides an introduction on how to work with dictionaries in KDB-X.
Overview
- Syntax
- Empty and singleton dictionaries
- Dictionary literal syntax
- Lookup
- Reverse lookup
- Taking and dropping from a dictionary
- Joining dictionaries
- Column dictionaries
- Step dictionaries
Syntax
A dictionary is a mapping from a list of keys to a list of values.
Syntax:
k!v ![k;v]
Where:
- Returns a dictionary in which
kis the key andvis the value - The keys
kand valuesvare same-length lists - The keys
kshould be unique (no duplicates), but no error is signalled if duplicates are present. However, operations on dictionaries with duplicate keys are undefined - Items of
kandvcan be of any datatype, including dictionaries or tables
Keywords key and value return the key and value lists respectively.
All dictionaries have type 99h.
Example:
q)show d1:`tom`dick`harry!1040 59 27
tom | 1040
dick | 59
harry| 27
q)key d1
`tom`dick`harry
q)value d1
1040 59 27
q)type d1
99h
If you know the keys are unique you can set the u attribute on them, as below. The dictionary will then function as a hash table, and indexing will be faster.
q)show d2:(`u#`a`b`c)!100 200 300
a| 100
b| 200
c| 300
q)key d2
`u#`a`b`c
Empty and singleton dictionaries
Just like a list, a dictionary may be empty or have a single item.
But its key and value must still be lists. Therefore, you must enlist atoms for a singleton dictionary.
q)()!() / general empty dictionary
q)(`symbol$())!`float$() / typed empty dictionary
q)show sd:(enlist `a)!enlist 1 / singleton dictionary
a| 1
q)key sd
,`a
q)value sd
,1
Dictionary literal syntax
Dictionary literal syntax was introduced as part of kdb+ 4.1.
With dictionary literals, you can concisely define dictionaries, and it removes the need to enlist atoms for singleton dictionaries:
q)enlist[`aaa]!enlist 123 / 4.0 syntax
aaa| 123
q)([aaa:123]) / 4.1 literal syntax
aaa| 123
This syntax follows rules consistent with list and table literal syntax:
q)([0;1;2]) / implicit key names (when omitted, default key names are assigned)
x | 0
x1| 1
x2| 2
q)d:([a:101;b:]);d 102 / missing values create projections
a| 101
b| 102
q)d each `AA`BB`CC / create a list of dictionaries (table) via projection
a b
------
101 AA
101 BB
101 CC
Similar to list literal syntax (;..), omission of values results in projection:
q)([k1:;k2:])[1;"a"]
k1| 1
k2| "a"
Lookup
To find the output value corresponding to an input key, we look up the key. Lookup uses the same notation as indexing into a list:
q)k:`a`b`c`d`e
q)v:10 20 30 40 50
q)show dict:k!v
a| 10
b| 20
c| 30
d| 40
e| 50
q)dict[`d`b] / indexing
40 20
q)v[3 1]
40 20
q)dict `d`b / brackets not necessary for indexing
40 20
q)v 3 1
40 20
q)v 5 / indexing out of domain works as for lists
0N / returns a null of same type of the first value item
q)dict `x
0N
Reverse lookup
Reverse lookups can be done on dictionaries using keywords where and find.
Example:
q)show d:`a`b`c`d!10 20 30 10
a| 10
b| 20
c| 30
d| 10
q)where d=20 / where
,`b
q)where d=40
`symbol$()
q)where d=10
`a`d
q)d?30 / find
`c
q)d?40 / indexing out of domain works as for lists
` / returns a null of same type of the first key item
q)d?10
`a / unlike where, find only returns the first match
Taking and dropping from a dictionary
Dictionaries are ordered, so you can take and drop items from either end of them.
Example:
q)show d:`a`b`c`d!10 20 30 10
a| 10
b| 20
c| 30
d| 10
q)-2#d
c| 30
d| 10
q)-1 _ d
a| 10
b| 20
c| 30
You can also take and drop selected items:
q)`b`d#d
b| 20
d| 10
q)`b`x _ d
a| 10
c| 30
d| 10
Joining dictionaries
The Join operator (,) merges two dictionaries.
Join on dictionaries has upsert semantics for common keys. If a key exists in both dictionaries, the value from the right-hand dictionary will overwrite the value from the left dictionary. New keys are appended to the end.
Example:
q)show d1:`a`b`c!10 20 30
a| 10
b| 20
c| 30
q)show d2:`c`d!400 500
c| 400
d| 500
q)d1,d2
a| 10
b| 20
c| 400
d| 500
Column dictionaries
When a dictionary’s value items are all same-length lists, it is called a column dictionary. Column dictionaries are the foundation for tables.
Example:
q)show bd:`name`dob`sex!(`jack`jill`john;1982.09.15 1984.07.05 1990.11.16;`m`f`m)
name| jack jill john
dob | 1982.09.15 1984.07.05 1990.11.16
sex | m f m
q)count each value bd
3 3 3
Flip a column dictionary and the result is a table:
q)flip bd
name dob sex
-------------------
jack 1982.09.15 m
jill 1984.07.05 f
john 1990.11.16 m
q)type flip bd
98h
Step dictionaries
A step dictionary is a dictionary with the sorted attribute applied. This will have the effect of referencing the preceding dictionary entry instead of returning a null for keys which don't exist.
Note
The sorted attribute needs to be applied to the keys of the dictionary, as well as to the dictionary as a whole for it to function as a step dictionary. If the keys are unsorted, 's-fail will be thrown when you try to create a step dictionary.
An as-of join is an example of a step dictionary - it joins the prevailing value to the time field in the join.
Example:
q)dict:`s#1 10 5!0.2 0.5 0.75 // unsorted keys, 's-fail
's-fail
[0] dict:`s#1 10 5!0.2 0.5 0.75
^
q)show dict:`s#1 5 10!0.2 0.5 0.75
1 | 0.2
5 | 0.5
10| 0.75
q)0N!dict; // `s# applied to the keys as well as dict itself
`s#`s#1 5 10!0.2 0.5 0.75
q)dict 1
0.2
q)dict 3
0.2
q)dict 5
0.5
q)dict 6
0.5
q)dict 99
0.75
Summary
In this guide, you learned how to:
- Create empty, singleton and multiplex dictionaries
- Create dictionaries using dictionary literal syntax
- Do lookups and reverse lookups on dictionaries
- Take and drop from dictionaries
- Join dictionaries
- Flip column dictionaries to create tables
- Create and lookup step dictionaries
For additional detail on dictionaries, check out Q for Mortals §5. Dictionaries
You now have the essential skills to work with dictionaries in KDB-X.