[kdb+/q]:将邻接矩阵转换为邻接表
[kdb+/q]: Convert adjacency matrix to adjacency list
给定(矩形)邻接矩阵m
,如何用q
语言构造邻接表?
在 QIdioms wiki 中,我找到了 k
语言的解决方案,当 运行 通过 q
控制台和 k)
命令时,我得到 '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
的^
a.k.a。 shape
q
中缺少动词,所以我就这样做了:
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 has q solution 用于反问题:从 adj.list 到 adj.matrix。
你有错误,因为原始的 Q 习语是用 k2 写的 - 一个旧版本的 k,现代 kdb+ 版本不支持。 k 的当前版本是 k4,它不向后兼容 k2。
例如,X _vs Y
其中 X 和 Y 是整数原子或旧 k2 中的列表表现得像 X vs Y
will 从 3.4t 开始在 kdb+ 中表现2015.12.13: http://code.kx.com/q/ref/lists/#vs:
Since 3.4t 2015.12.13: For integer types, computes the base representation of Y in the radices X.
再举个例子。事实上,k2 中的 ^
是一个形状运算符,但现在不再是了。在 k2 ^m
中,您的示例中的矩阵 m
会 returned 2 3
,而目前的实现行为与 q
的 not null
一样据我了解。
现在,回到您最初的问题,"how to construct adjacency list in q
language"。一种方法是这样的:
q)lm:{flip raze(til count x),''where each x}
或
k)lm:{+,/(!#x),''&:'x}
更新:这是它的工作原理。如果我们要使用任何 "verbose" 语言构建邻接表,我们会做这样的事情:
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)
可以 "translated" 变成 til count M
因为 count
将 return 顶层元素的数量,即行数。 (2)
和(3)
组合起来可以表示为where each M
。实际上,对于每一行,我们 return 非零元素的位置。给定一个原始矩阵 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)
的每个元素的每个元素连接起来,因此 ,''
.
中的双撇号
我希望它现在有意义。
就我个人而言,我不会使用 flip
(或 +
in k),我无法读取这种形式的邻接矩阵:
0 0 1 1
0 2 0 2
我认为这更具可读性:
0 0
0 2
1 0
1 2
但这当然取决于你。
给定(矩形)邻接矩阵m
,如何用q
语言构造邻接表?
在 QIdioms wiki 中,我找到了 k
语言的解决方案,当 运行 通过 q
控制台和 k)
命令时,我得到 '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
的^
a.k.a。 shape
q
中缺少动词,所以我就这样做了:
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 has q solution 用于反问题:从 adj.list 到 adj.matrix。
你有错误,因为原始的 Q 习语是用 k2 写的 - 一个旧版本的 k,现代 kdb+ 版本不支持。 k 的当前版本是 k4,它不向后兼容 k2。
例如,X _vs Y
其中 X 和 Y 是整数原子或旧 k2 中的列表表现得像 X vs Y
will 从 3.4t 开始在 kdb+ 中表现2015.12.13: http://code.kx.com/q/ref/lists/#vs:
Since 3.4t 2015.12.13: For integer types, computes the base representation of Y in the radices X.
再举个例子。事实上,k2 中的 ^
是一个形状运算符,但现在不再是了。在 k2 ^m
中,您的示例中的矩阵 m
会 returned 2 3
,而目前的实现行为与 q
的 not null
一样据我了解。
现在,回到您最初的问题,"how to construct adjacency list in q
language"。一种方法是这样的:
q)lm:{flip raze(til count x),''where each x}
或
k)lm:{+,/(!#x),''&:'x}
更新:这是它的工作原理。如果我们要使用任何 "verbose" 语言构建邻接表,我们会做这样的事情:
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)
可以 "translated" 变成 til count M
因为 count
将 return 顶层元素的数量,即行数。 (2)
和(3)
组合起来可以表示为where each M
。实际上,对于每一行,我们 return 非零元素的位置。给定一个原始矩阵 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)
的每个元素的每个元素连接起来,因此 ,''
.
我希望它现在有意义。
就我个人而言,我不会使用 flip
(或 +
in k),我无法读取这种形式的邻接矩阵:
0 0 1 1
0 2 0 2
我认为这更具可读性:
0 0
0 2
1 0
1 2
但这当然取决于你。