修改单个元素的横截面

Amend cross sections for single element

我正在玩 https://code.kx.com/q/ref/amend/#cross-sections

上的一个例子
$ q
KDB+ 3.6 2019.04.02 Copyright (C) 1993-2019 Kx Systems
q)d:((1 2 3;4 5 6 7);(8 9;10;11 12);(13 14;15 16 17 18;19 20))
q)i:(2 0; 0 1 0)
q)y:(100 200 300; 400 500 600)
q)r:.[d; i; ,; y]

一切正常,除非我尝试引用单个元素 d[1;1]:

q)i:(1 0; 0 1 0)
q)r:.[d; i; ,; y]
'type
  [0]  r:.[d; i; ,; y]

但是如果我对列表使用 join , 并且只对单个元素使用它,它会按预期工作:

q)10,200
10 200
q)10,((),200)
10 200

那么为什么修改操作会在这个简单的连接上中断?

更新:

再举一个例子:

q)@[(1; 2; 3);1;,;10]
'type
  [0]  @[(1; 2; 3);1;,;10]
       ^

但如果使用列表就可以了:

q)@[(1; (),2; 3);1;,;10]
1
2 10
3

我能提供的唯一解释是 kdb+ 在可能的情况下尝试使用就地修改(也称为 assignment through the operator)。

例如,这个有效:

q)l:(13 14;15 16 17 18;19 20)
q)l[1],:200
q)l
13 14
15 16 17 18 200
19 20

但事实并非如此:

q)l:(8 9;10;11 12)
q)l[1],:200
'type
[0]  l[1],:200
       ^

后者失败是因为 kdb 无法用 vector 10 200 替换 atom 10 - - 更改类型不是就地修改应该做的事情。

如果你使用自己的函数 {x,y} 而不是加号 运算符 第二个 您的示例中的表达式也将按预期工作,因为 kdb 将 replace 现有值与函数的 return 值(与内置 , , 就 kdb 而言是一个黑盒子):

q)i:(1 0; 0 1 0)
q)r:.[d; i; ,; y]
q).[d; ii; {x,y}; y]
(1 2 3 400 600;4 5 6 7 500)
(8 9 100 300;10 200;11 12)
(13 14;15 16 17 18;19 20)

答案在于检查您提取要加入的数据,这里运算符 -3! 是您的朋友,可帮助您通过多层征募揭示实际结构

q)d:((1 2 3;4 5 6 7);(8 9;10;11 12);(13 14;15 16 17 18;19 20))
q)i1:(2 0; 0 1 0)
q)i2:(1 0; 0 1 0)
q)y:(100 200 300; 400 500 600)
q)-3!r1:.[d; i1]
"((13 14;15 16 17 18;13 14);(1 2 3;4 5 6 7;1 2 3))"
q)q){type each x} each .[d; i1]
7 7 7
7 7 7
q)-3!r2:.[d; i2]
"((8 9;10;8 9);(1 2 3;4 5 6 7;1 2 3))"
q){type each x} each .[d; i2]
7 -7 7
7 7  7

不在这里我们可以看到,在第一种情况下,r1 的每个元素都是列表的列表,但对于 r2,第一个元素是 2 个具有原子长 10

来自横截面文档

The shape of y is 2 3, the same shape as the cross-section selected by d . i

即Shape应该是计数和类型匹配,y的每一项的类型是一个7h,应该匹配d中每个选择的类型。

本质上,当您使用修正运算符 ,@ 时,它将期望符合性,因为它正在使用修正。 a:1;a,:1 2 3 也会失败。

我们可以用你的其他例子来证实这一点

q)type @[(1; (),2; 3);1]
7h

更改该示例以调整第一个元素

q)@[(1; (),2; 3);0;,;10]
'type

仅将 , 运算符用作 10,((),200) 不会导致任何错误的原因是因为您在修改重载之外,在修改重载 , 中使用它期望使用匹配的形状。直接使用可促进和调整形状。