Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

kdb q - apply each-left for each atom in list and reduce

Tags:

q-lang

kdb+

I would like to apply each-left between a column of a table and each atom in a list. I cannot use each-both because the table column and the list are not of same length.

I have seen this done in one line somewhere already but I can't find it anymore..

Example:

t:([] name:("jim";"john";"john";"julia");c1: til 4);
searchNames:("jim";"john");
f:{[name;nameCol] nameCol like\:name}; / each-left between name (e.g. "jim") and column
g:f[;t[`name]];
r:g each searchNames; / result: (1000b;0110b)
filter:|/[r];     / result: 1110b
select from t where filter 

How can I do that more q-like?

like image 276
tenticon Avatar asked Jan 01 '26 08:01

tenticon


2 Answers

If you wish to use like with each-right /::

q)select from t where any name like/:searchNames
name   c1
---------
"jim"  0
"john" 1
"john" 2

In this case you can simply use in as you are not using any wildcards:

q)select from t where name in searchNames
name   c1
---------
"jim"  0
"john" 1
"john" 2
like image 95
Thomas Smyth - Treliant Avatar answered Jan 02 '26 21:01

Thomas Smyth - Treliant


Below is a generic function you could use, given two lists of different sizes.

q)f:{(|) over x like/:y}
q)
q)select from t where f[name;searchNames]
name   c1
---------
"jim"  0
"john" 1
"john" 2

Or, wrapping it up in a single function (assuming always searching a table column):

q)f2:{x where (|) over (0!x)[y] like/:z}
q)
q)f2[t;`name;searchNames]
name   c1
---------
"jim"  0
"john" 1
"john" 2

But in the scenario you describe, Thomas' solution seems the most natural.

like image 30
James Little Avatar answered Jan 02 '26 23:01

James Little



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!