Core Concepts

Dictionaries

Key-value mappings, operations, nesting, and the relationship between dictionaries and tables.

Creating Dictionaries

A dictionary maps a list of keys to a list of values using the ! operator:

/ Syntax: keys ! values
d: `a`b`c ! 1 2 3

/ String keys
sd: ("alpha";"beta";"gamma") ! 10 20 30

/ Symbol to float
prices: `AAPL`GOOG`MSFT ! 182.5 2840.0 310.2

Accessing Values

d[`a]        / 1
d[`b`c]      / 2 3  (multiple lookup)
d `a         / 1    (juxtaposition syntax)

prices[`AAPL]   / 182.5

Key and Value Extraction

key d        / `a`b`c   (keys)
value d      / 1 2 3    (values)

count d      / 3

Modifying Dictionaries

Assigning to a key updates the dictionary in place. If the key does not exist yet, it is added:

d[`d]: 4          / add a new key: d is now `a`b`c`d!1 2 3 4
d[`a]: 99         / update an existing key: d is now `a`b`c`d!99 2 3 4

/ Drop a key with _ (this returns a new dictionary; d itself is unchanged)
`b _ d            / `a`c`d!99 3 4

Dictionary Arithmetic

When dictionaries share keys, arithmetic operates key-by-key:

d1: `a`b`c ! 1 2 3
d2: `a`b`c ! 10 20 30

d1 + d2      / `a`b`c ! 11 22 33
d1 * d2      / `a`b`c ! 10 40 90

/ Different key sets — result is union of keys
d3: `a`b ! 1 2
d4: `b`c ! 20 30
d3 + d4      / `a`b`c ! 1 22 30

Mixed Values and Nested Dictionaries

Values do not have to share a type. Here the values are a symbol, a float and a long:

trade: `sym`price`size ! (`AAPL; 182.5; 100)

trade[`sym]      / `AAPL
trade[`price]    / 182.5

A value can itself be a dictionary. Index the outer dictionary, then the inner one:

quote: `bid`ask ! (`price`size!(100.1;500); `price`size!(100.2;300))

quote[`bid;`price]   / 100.1
quote . `ask`size    / 300

Flip: Dictionaries to Tables

A table in kdb+ is a flipped dictionary where each value is a list of equal length:

/ Dictionary of lists → table
d: `sym`price`size ! (`AAPL`GOOG`MSFT; 182.5 2840.0 310.2; 100 50 200)
t: flip d

/ Now t is a table
meta t
c    | t f a
-----| -----
sym  | s
price| f
size | j

Key insight: Every table in kdb+ is a flipped column dictionary. Understanding this relationship is fundamental to working effectively with kdb+.

The ! Operator — Many Meanings

The ! operator is overloaded in q. Its meaning depends on its arguments:

/ Dict: create a dictionary from keys and values
`a`b ! 1 2

/ Key: make the first column of table t the key (a keyed table)
1!t

/ An empty dictionary
()!()

! does not compute a remainder; use mod for that: 7 mod 3 is 1. See the KX reference page for ! for its other forms (enumeration and the functional forms of update and delete).

Practical Example: Aggregating a Trade Log

/ Simulate a trade log
syms:  `AAPL`GOOG`AAPL`MSFT`AAPL`GOOG
sizes: 100 50 200 300 150 75

/ group returns a dictionary: each distinct item -> the indices where it occurs
g: group syms
/ g is `AAPL`GOOG`MSFT!(0 2 4;1 5;,3)

/ Index sizes with each list of indices, then sum each group
sum each sizes g
/ `AAPL`GOOG`MSFT!450 125 300

Writing syms ! sizes instead would build a dictionary with duplicate keys, and a lookup such as (syms!sizes)[`AAPL] returns only the first match (100), so it cannot be used to aggregate.

Finding Keys

d: `a`b`c ! 10 20 30

/ ? finds key by value
d ? 20       / `b

/ in checks membership
`b in key d  / 1b
`x in key d  / 0b