乐趣区

5. Q语言学习之路—字典

1. 字典基础
1. 定义字典是 key-values pairs,但是在 q 中,字典是按照 list 来存储的。字典的创建使用操作符!,读作 bang :) 所有的字典类型都是 99h。
q)10 20 30!1.1 2.2 3.3
10| 1.1
20| 2.2
30| 3.3

q)`a`b`c!100 200 300
a| 100
b| 200
c| 300
可以使用操作符 key, value, count 来分别获取字典的键、值和个数。
尽管 q 语言不强制键的唯一性(historical mistake),但是却对每个输入值都提供唯一的输出,只有第一次出现的 key 会被看到。
当你知道字典的键是 unique 的时候,可以使用命令 `u# 将字典转换为哈希表,这样与原来的线性搜索相比,会提高查找的速度。
q)(`u#`a`b`c)!10 20 30
注意:与传统语言不一样,不同顺序的字典在 q 中是不等的。
q)(`a`b`c!10 20 30)~`a`c`b!10 30 20
0b
2. 空和单例字典
空字典:
()!()
带类型的空字典:
`symbol$()!`float$()
单例字典,必须要使用 enlist 形式先生成一个 list,否则会报错
q)(enlist `x)!enlist 42
x| 42
3. 查找使用中括号或者并列的形式:
q)d:`a`b`c!10 20 30
q)d[`a]
10
q)d `b
20
当查找值不在字典的键表中时,返回值列表中初始值类型的 Null 值:
q)d[`x]
0N
4. 逆向查找 使用? 与列表类似,? 返回值在字典中对应的键。
q)d:`a`b`c`a!10 20 30 10
q)d?10
`a
当查找的值不在字典的值列表中时,返回键列表中初始值类型的 Null 值:
q)d:`a`b`c`a!10 20 30 10
q)d?40
`
5. 字典和列表 可以通过字典来表示一个稀疏列表:
q)d1:0 100 500000!10 20 30
q)d2:0 99 1000000!100 200 300
q)d1+d2
0 | 110
100 | 20
500000 | 30
99 | 200
1000000| 300
6. 不唯一的键和值 如之前所说,当键不唯一时,会返回第一个出现时的值:
q)ddup:`a`b`a`c!10 20 30 20
q)ddup[`a]
10
逆向查找同理:
q)ddup?30
`a
q)ddup?20
`b
7. Non-simple 键 和 值
键和值是嵌套的列表:
q)d:(`a`b; `c`d`e; enlist `f)!10 20 30
q)d `f
30
q)d?20
`c`d`e
q)d:`a`b`c!(10 20; 30 40 50; enlist 60)
q)d `b
30 40 50
q)d?30 40 50
`b
q)d?enlist 60

注意,对单个元素的键或值要单独对其生成一个列表(enlist),否则会有如下的问题:
q)dwhackey:(1 2; 3 4 5; 6; 7 8)!10 20 30 40 / atom 6 is whack
q)dwhackey 1 2
10
q)dwhackey 6
0N
q)dwhackval:10 20 30 40!(1 2; 3 4 5; 6; 7 8) / atom 6 is whack
q)dwhackval?3 4 5
20
q)dwhackval?6
0N
会导致查找失败,返回 Null 值。
2. 字典操作
1. Amend 和 Upsert
update:
q)d:`a`b`c!10 20 30
q)d[`b]:42
insert:
q)d:`a`b`c!10 20 30
q)d[`x]:42
在 q 语言中,update/insert 操作被称为 upsert 操作。
2. 提取子字典使用提取操作符 #,左运算元为子字典的键,右运算元为原始字典。另外,当原始字典有重复键时,只会提取第一次出现的键:
q)ddup:`a`b`a`c!10 20 30 20
q)`a`c#ddup
a| 10
c| 20
3. 删除 使用操作符_,用法与 #类似,但需要注意_前后要加空格。
q)d:`a`b`c!10 20 30
q)`a`c _ d
b| 20
q)(enlist `b) _ d
删除全部键值对会得到一个带类型的空字典:
q)d:`a`b`c!10 20 30
q)`a`b`c _ d
q)-3!`a`b`c _ d
“(`symbol$())!`long$()”
操作符 cut 与_在字典上的效果相同。
另外一个很少用的用法是,字典在_的左边,_右运算元为一个单一的键,表示字典删除这个键:
q)d _ `b
a| 10
c| 30
4. 字典上的基础运算一些常见的基础运算如下例所示,非常容易理解
q)d:`a`b`c!10 20 30
q)neg d
a| -10
b| -20
c| -30
字典的加法:相同键值进行加法操作,不同键值保留下来
q)d1:`a`b`c!1 2 3
q)d2:`b`c`d!20 30 40
q)d1+d2
a| 1
b| 22
c| 33
d| 40
5. join, 使用, 进行合并字典的操作,由于 q 语言是 right to left 特性的,所以合并的两个字典如果有相同的键值,那么右边的会保留下来。
q)d1:`a`b`c!10 20 30
q)d2:`c`d!300 400
q)d1,d2
a| 10
b| 20
c| 300
d| 400
因此,字典合并时,前后顺序很重要。
6. Coalesce ^ 这种合并方式类似于, 合并,但与其不同的是,当 ^ 右边右边项值为 Null 时不覆盖左边项,见下例:
q)d1:`a`b`c!10 0N 30
q)d2:`b`c`d!200 0N 400

q)d1^d2
a| 10
b| 200
c| 30
d| 400

q)d1,d2
a| 10
b| 200
c|
d| 400
7. 算术和相等运算符 对于相等性比较,由于 null 代表缺失值,所以所有的 null 值会被认为是相等的。
q)(`a`b`c!10 20 30)=`b`c`d!20 300 400
a| 0
b| 1
c| 0
d| 0
q)(`a`b`c!0N 20 30)=`b`c`d!20 300 0N
a| 1
b| 1
c| 0
d| 1
q)(`a`b`c!10 20 30)<`b`c`d!20 300 400
a| 0
b| 0
c| 1
d| 1
3. 列字典
列字典 (Column Dictionary) 是表 (Table) 的基础。
1. 定义和术语一个一般的列字典具有如下的形式:
c1…cn!(v1;…;vn)
其中 ci 是 symbol 类型,vi 是具有相同长度的列表。通常 vi 均为简单列表。
2. 简单例子
q)travelers:`name`iq!(`Dent`Beeblebrox`Prefect;42 98 126)
q)travelers
name| Dent Beeblebrox Prefect
iq | 42 98 126
索引:
q)travelers[`name; 1]
`Beeblebrox
q)travelers[`iq; 2]
126
单列的字典:
q)dc1:(enlist `c)!enlist 10 20 30
q)dc1
c| 10 20 30
4. 列字典的翻转
q)dc:`c1`c2!(`a`b`c; 10 20 30)
q)dc
c1| a b c
c2| 10 20 30
q)t:flip dc
q)t
c1 c2
—–
a 10
b 20
c 30
索引:
q)dc[`c1; 0]
`a
q)dc[`c1; 1]
`b
q)dc[`c1; 2]
`c
q)t[0; `c1]
`a
q)t[1; `c1]
`b
q)t[2; `c1]
`c
Unlike the case of transposing rectangular lists, transposing a column dictionary does not physically re-arrange data.(翻转并不会改变数据的存储)

退出移动版