user7613376
user7613376

Reputation:

Understanding how to read each-right and each-left combined in kdb

From q for mortals, i'm struggling to understand how to read this, and understand it logically.

1 2 3,/:\:10 20

I understand the result is a cross product when in full form: raze 1 2 3,/:\:10 20.

But reading from left to right, I'm currently lost at understanding what this yields (in my head)

\:10 20

combined with 1 2 3,/: ??

Help in understanding how to read this clearly (in words or clear logic) would be appreciated.

Upvotes: 1

Views: 2313

Answers (2)

Chromozorz
Chromozorz

Reputation: 461

I found myself saying the following in my head whilst I program the syntax in q. q works from right to left.

Internal Monologue ->  Join the string on the right onto each of the strings on the left
code ->                "ABC",\:"-D"
result ->              "A-D"
                       "B-D" 
                       "C-D"

I think that's an easy way to understand it. 'join' can be replaced with whatever...

Internal Monologue ->  Does the string on the right match any of the strings on the left
code ->                ("Cat";"Dog";"CAT";"dog")~\:"CAT"
result ->              0010b

Each-right is the same concept and combining them is straightforward also;

Internal Monologue ->  Does each of the strings on the right match each of the strings on the left
code ->                ("Cat";"Dog";"CAT";"dog")~\:/:("CAT";"Dog")
result ->              0010b
                       0100b   

So in your example 1 2 3,/:\:10 20 - you're saying 'Join each of the elements on the right to each of the elements on the left'

Hope this helps!!

EDIT To add a real world example.... - consider the following table

q)show tab:([] upper syms:10?`2; names:10?("Robert";"John";"Peter";"Jenny"); amount:10?til 10)
syms names    amount
--------------------
CF   "Peter"  8
BP   "Robert" 1
IC   "John"   9
IN   "John"   5
NM   "Peter"  4
OJ   "Jenny"  6
BJ   "Robert" 6
KH   "John"   1
HJ   "Peter"  8
LH   "John"   5
q)

I you want to get all records where the name is Robert, you can do; select from tab where names like "Robert"

But if you want to get the results where the name is either Robert or John, then it is a perfect scenario to use our each-left and each-right.

Consider the names column - it's a list of strings (a list where each element is a list of chars). What we want to ask is 'does any of the strings in the names column match any of the strings we want to find'... that translates to (namesList)~\:/:(list;of;names;to;find). Here's the steps;

q)(tab`names)~\:/:("Robert";"John")
0100001000b
0011000101b

From that result we want a compiled list of booleans where each element is true of it is true for Robert OR John - for example, if you look at index 1 of both lists, it's 1b for Robert and 0b for John - in our result, the value at index 1 should be 1b. Index 2 should be 1b, index3 should be 1b, index4 should be 0b etc... To do this, we can apply the any function (or max or sum!). The result is then;

q)any(tab`names)~\:/:("Robert";"John")
0111001101b

Putting it all together, we get;

q)select from tab where any names~\:/:("Robert";"John")
syms names    amount
--------------------
BP   "Robert" 1
IC   "John"   9
IN   "John"   5
BJ   "Robert" 6
KH   "John"   1
LH   "John"   5
q)

Upvotes: 4

Paul Kerrigan
Paul Kerrigan

Reputation: 465

Firstly, q is executed (and hence generally read) right to left. This means that it's interpreting the \: as a modifier to be applied to the previous function, which itself is a simple join modified by the /: adverb. So the way to read this is "Apply join each-right to each of the left-hand arguments."

In this case, you're applying the two adverbs to the join - \:10 20 on its own has no real meaning here.

I find it helpful to also look at the converse case 1 2 3,\:/:10 20, running that code produces a 2x6 matrix, which I'd describe more like "apply join each-left to each of the right hand arguments" ... I hope that makes sense.

An alternative syntax which also might help is ,/:\:[1 2 3;10 20] - this might be useful as it makes it very clear what the function you're applying is, and is equivalent to your in-place notation.

Upvotes: 0

Related Questions