0

Given a table and a function

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
 };

I noticed that when applying the function f onto columns of t, then the entire columns are passed into f and if they can be operated on atomically then the output will be of the same length as the inputs and a new column is produced. However in our example this wont work:

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

because the inner functions symf and datef cannot be applied to the entire column c2, c3, respectively.

If I dont want to change the function f at all, how can I apply it row by row and collect the values into a new column in t.

What's the most q style way to do this?

EDIT

If not changing f is really inconvenient one could workaround like so

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)

Still I would be interested how to get the same result when working with the original version of f

Thanks!

Jonathon McMurray
  • 2,881
  • 1
  • 10
  • 22
tenticon
  • 2,639
  • 4
  • 32
  • 76

1 Answers1

3

You can use each-both for this e.g.

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

However you will likely get better performance by modifying f to be "vectorised" e.g.

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

In general in KDB, if you can avoid using any form of each and stick to vector operations, you'll get much more efficiency

Jonathon McMurray
  • 2,881
  • 1
  • 10
  • 22