KDB+/Q:单行表和多行表的输入不可知函数
KDB+/Q:Input agnostic function for single and multi row tables
我尝试使用以下函数派生一个 table 由 3 列组成,其中一列 data
包含任意模式的列表。
fn:{
flip `time`data`id!(x`b;(x`a`b`c`d`e);x`a)
};
这对多行输入效果很好,即:
q)x:flip `a`b`c`d`e!(5#enlist 5?10)
q)fn[`time`data`id!(x`b;(x`a`b`c`d`e);x`a)]
time data id
-----------------
8 8 5 2 8 6 8
5 8 5 2 8 6 5
2 8 5 2 8 6 2
8 8 5 2 8 6 8
6 8 5 2 8 6 6
然而,当使用单行输入时失败,即
q)x:`a`b`c`d`e!5?10
q)fn[`time`data`id!(x`b;(x`a`b`c`d`e);x`a)]
time data id
------------
8 7 7
8 8 7
8 4 7
8 4 7
8 6 7
这显然是不正确的。
人们可能会通过使用 enlist 来解决这个问题,即
q)x:enlist `a`b`c`d`e!5?10
q)fn[`time`data`id!(x`b;(x`a`b`c`d`e);x`a)]
time| 8
data| 7 8 4 4 6
id | 7
这是正确的,但是如果在函数中应用它,即
fn:{
flip enlist `time`data`id!(x`b;(x`a`b`c`d`e);x`a)
};
...
time| 2 5 8 7 9
data| 2 5 8 7 9 2 5 8 7 9 2 5 8 7 9 2 5 8 7 9 2 5 8 7 9
id | 2 5 8 7 9
数据值格式错误。
我的问题是如何避免这个转换问题并导出相同的字段值,无论参数是多行还是单行 table。
或者在 kdb+/q 中这个的规范实现是什么
谢谢
编辑:
澄清一下:我的问题不一定与数据输入有关,因为如果只有一行,则可以申请入伍。我的问题涉及如何在 fn 函数中使用 enlist 使单行输入符合使用多行 tables 时看到的逻辑。即如何用 fn 数据替换 fn enlist input
(如何使函数输入不可知)谢谢
您的意思是翻转数据与 table 的其余部分垂直吗?您的 5 行示例有效,因为有 5 行和 5 列。由于 1 行到 5 列,单行不起作用。
如果我错了请纠正我,但我认为这就是你想要的:
fn:{([]time:x`b;data:flip x`a`b`c`d`e;id:x`a)};
--------------------------------------------------
t1:flip `a`b`c`d`e!(5#enlist til 5);
a b c d e
---------
0 0 0 0 0
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
fn[t1]
time data id
-----------------
0 0 0 0 0 0 0
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
4 4 4 4 4 4 4
--------------------------------------------------
t2:enlist `a`b`c`d`e!til 5;
a b c d e
---------
0 1 2 3 4
fn[t2]
time data id
-----------------
1 0 1 2 3 4 0
注意没有翻转你得到这个:
([]time:t1`b;data:t1`a`b`c`d`e;id:t1`a)
time data id
-----------------
0 0 1 2 3 4 0
1 0 1 2 3 4 1
2 0 1 2 3 4 2
3 0 1 2 3 4 3
4 0 1 2 3 4 4
在这种情况下,时间不再与数据一致,但由于有 5 行和列,所以可以正常工作。
编辑 - 除了在条件中首先使用 count 之外,我想不出更好的方法在需要时将字典转换为 table。请注意,如果第一个键是嵌套列表,这将不起作用
{ $[1 = count first x;enlist x;x] } `a`b`c`d`e!til 5
请注意,您提供的函数不适用于此:
{
flip `time`data`id!(x`b;(x`a`b`c`d`e);x`a)
}{$[1 = count first x;enlist x;x]} `a`b`c`d`e!til 5
我尝试使用以下函数派生一个 table 由 3 列组成,其中一列 data
包含任意模式的列表。
fn:{
flip `time`data`id!(x`b;(x`a`b`c`d`e);x`a)
};
这对多行输入效果很好,即:
q)x:flip `a`b`c`d`e!(5#enlist 5?10)
q)fn[`time`data`id!(x`b;(x`a`b`c`d`e);x`a)]
time data id
-----------------
8 8 5 2 8 6 8
5 8 5 2 8 6 5
2 8 5 2 8 6 2
8 8 5 2 8 6 8
6 8 5 2 8 6 6
然而,当使用单行输入时失败,即
q)x:`a`b`c`d`e!5?10
q)fn[`time`data`id!(x`b;(x`a`b`c`d`e);x`a)]
time data id
------------
8 7 7
8 8 7
8 4 7
8 4 7
8 6 7
这显然是不正确的。 人们可能会通过使用 enlist 来解决这个问题,即
q)x:enlist `a`b`c`d`e!5?10
q)fn[`time`data`id!(x`b;(x`a`b`c`d`e);x`a)]
time| 8
data| 7 8 4 4 6
id | 7
这是正确的,但是如果在函数中应用它,即
fn:{
flip enlist `time`data`id!(x`b;(x`a`b`c`d`e);x`a)
};
...
time| 2 5 8 7 9
data| 2 5 8 7 9 2 5 8 7 9 2 5 8 7 9 2 5 8 7 9 2 5 8 7 9
id | 2 5 8 7 9
数据值格式错误。 我的问题是如何避免这个转换问题并导出相同的字段值,无论参数是多行还是单行 table。 或者在 kdb+/q 中这个的规范实现是什么 谢谢
编辑:
澄清一下:我的问题不一定与数据输入有关,因为如果只有一行,则可以申请入伍。我的问题涉及如何在 fn 函数中使用 enlist 使单行输入符合使用多行 tables 时看到的逻辑。即如何用 fn 数据替换 fn enlist input
(如何使函数输入不可知)谢谢
您的意思是翻转数据与 table 的其余部分垂直吗?您的 5 行示例有效,因为有 5 行和 5 列。由于 1 行到 5 列,单行不起作用。
如果我错了请纠正我,但我认为这就是你想要的:
fn:{([]time:x`b;data:flip x`a`b`c`d`e;id:x`a)};
--------------------------------------------------
t1:flip `a`b`c`d`e!(5#enlist til 5);
a b c d e
---------
0 0 0 0 0
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
fn[t1]
time data id
-----------------
0 0 0 0 0 0 0
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
4 4 4 4 4 4 4
--------------------------------------------------
t2:enlist `a`b`c`d`e!til 5;
a b c d e
---------
0 1 2 3 4
fn[t2]
time data id
-----------------
1 0 1 2 3 4 0
注意没有翻转你得到这个:
([]time:t1`b;data:t1`a`b`c`d`e;id:t1`a)
time data id
-----------------
0 0 1 2 3 4 0
1 0 1 2 3 4 1
2 0 1 2 3 4 2
3 0 1 2 3 4 3
4 0 1 2 3 4 4
在这种情况下,时间不再与数据一致,但由于有 5 行和列,所以可以正常工作。
编辑 - 除了在条件中首先使用 count 之外,我想不出更好的方法在需要时将字典转换为 table。请注意,如果第一个键是嵌套列表,这将不起作用
{ $[1 = count first x;enlist x;x] } `a`b`c`d`e!til 5
请注意,您提供的函数不适用于此:
{
flip `time`data`id!(x`b;(x`a`b`c`d`e);x`a)
}{$[1 = count first x;enlist x;x]} `a`b`c`d`e!til 5