给定(矩形(邻接矩阵m
,如何用q
语言构造邻接列表?
在 QIdioms wiki 中,我找到了k
语言的解决方案,当使用k)
命令通过控制台运行时q
会给我'vs
错误:
m:(1 0 1;1 0 1)
k) (^m)_vs &,/m
'vs
结果应为:
0 0 1 1
0 2 0 2
这是我能够在q
中复制的内容:
k) &,/m
0 2 3 5
q) where raze m
0 2 3 5
k
^
又名 q
中缺少shape
动词,所以我只是做了:
k) (^m)
000b
000b
q) 2 3#0b
000b
000b
现在,因为:
q) parse "vs"
k) {x:y}
我尝试了两个都不成功:
q) (2 3#0b) _vs where raze m
'
q) (2 3#0b) _: where raze m
'type
请注意,QIdioms wiki 有 q 个反问题的解决方案:从 adj.list 到 adj.matrix。
你遇到了错误,因为原始的 Q 习语是用 k2 编写的——这是现代 kdb+ 版本不支持的 k 的旧版本。k的当前版本是k4,它与k2不向后兼容。
例如,X _vs Y
其中 X 和 Y 是整数原子或旧 k2 中的列表的行为类似于X vs Y
从 3.4t 开始在 kdb+ 中的行为 2015.12.13: http://code.kx.com/q/ref/lists/#vs:
自 3.4t 起 2015.12.13:对于整数类型,计算 Y 在 radices X 中的基数表示。
另一个例子。事实上,k2 中的^
是一个形状运算符,但它不再是。在 k2 中,^m
会从您的示例中返回矩阵m
的2 3
,而据我所知,当前的实现的行为类似于q
的not null
。
现在,回到你最初的问题,"如何用q
语言构建邻接列表"。一种方法是这样的:
q)lm:{flip raze(til count x),''where each x}
或
k)lm:{+,/(!#x),''&:'x}
更新:这是它的工作原理。如果我们要使用任何"详细"语言构建邻接列表,我们会做这样的事情:
for i = 0 to <number of rows> - 1 <---- (1)
for j = 0 to <number of columns> - 1 <---- (2)
if M[i;j] <> 0 <---- (3)
print i, j
在像q这样的数组语言中,(1)
可以"翻译"为til count M
,因为count
将返回顶级元素的数量,即行数。 (2)
和(3)
组合可以用where each M
表示。事实上,对于每一行,我们返回非零元素的位置。给定一个原始矩阵 m,我们将得到:
til count m -> 0 1
where each m -> (0 2; 0 2)
我们需要做的就是连接行索引和列索引。我们不能只使用,'
,因为它会将0
与第一个0 2
连接,1
与第二个0 2
一起,从而导致(0 0 2; 1 0 2)
。我们需要更深入一层,将左侧的每个元素与嵌套列表的每个元素的每个元素(0 2; 0 2)
右侧连接起来,因此,''
中的双撇号。
我希望现在有意义。
就个人而言,我不会在 k flip
(或 +
(,我无法读取这种形式的邻接矩阵:
0 0 1 1
0 2 0 2
我认为这更具可读性:
0 0
0 2
1 0
1 2
但这当然取决于你。