q - 在 table 行上应用函数

q - apply function on table rowwise

给定一个 table 和一个函数

t:([] c1:1 2 3; c2:`a`b`c; c3:13:00 13:01 13:02)
f:{[int;sym;date] 
    symf:{$[x=`a;1;x=`b;2;3]};
    datef:{$[x=13:00;1;x=13:01;2;3]};
    r:int + symf[sym] + datef[date];
    r
 };

我注意到,当将函数 f 应用到 t 的列时,整个列都被传递到 f,如果它们可以原子操作,那么输出将与输入长度相同,并生成一个新列。然而,在我们的示例中,这是行不通的:

update newcol:f[c1;c2;c3] from t / 'type error

因为内部函数 symfdatef 不能分别应用于整个列 c2c3

如果我 根本不想 更改函数 f,我该如何逐行应用它并将值收集到 t 中的新列中。

q 风格的方法是什么?

编辑

如果不改变 f 真的很不方便,可以像这样解决

f:{[arglist]
    int:arglist 0;
    sym:arglist 1;
    date:arglist 2; 
    symf:{$[x=`a;1;x=`b;2;3]};
    datef:{$[x=13:00;1;x=13:01;2;3]};
    r:int + symf[sym] + datef[date];
    r
 };

f each (t`c1),'(t`c2),'(t`c3)

我仍然对如何在使用 f

的原始版本时获得相同的结果感兴趣

谢谢!

您可以为此使用 each-both,例如

q)update newcol:f'[c1;c2;c3] from t
c1 c2 c3    newcol
------------------
1  a  13:00 3
2  b  13:01 6
3  c  13:02 9

然而,将 f 修改为 "vectorised" 可能会获得更好的性能,例如

q)f2
{[int;sym;date]
    symf:3^(`a`b!1 2)sym;
    datef:3^(13:00 13:01!1 2)date;
    r:int + symf + datef;
    r
 }
q)update newcol:f2[c1;c2;c3] from t
c1 c2 c3    newcol
------------------
1  a  13:00 3
2  b  13:01 6
3  c  13:02 9
q)\ts:1000 update newcol:f2[c1;c2;c3] from t
4 1664
q)\ts:1000 update newcol:f'[c1;c2;c3] from t
8 1680

一般来说,在 KDB 中,如果你能避免使用任何形式的 each 并坚持向量操作,你将获得更高的效率