cjm2671
cjm2671

Reputation: 19466

How do I test a range in KDB?

Let's say I have a range 3 < x < 5.

What's the cleanest way to get 1 if x > 5, -1 if x < 3 and 0 if it's in the range 3 <x <5?

I'm trying to mix together & and | (trying to adapt the answer from here: In KDB/Q, how do I clip numbers to be in the range -1, 1?). I'm not sure if it's possible this way though.

Upvotes: 2

Views: 321

Answers (4)

Cathal O&#39;Neill
Cathal O&#39;Neill

Reputation: 3179

Another option:

q){$[x<3;-1;x>5;1;0]}each til 10
-1 -1 -1 0 0 0 1 1 1 1

Upvotes: 1

MurrMack
MurrMack

Reputation: 579

As an aside Sean and Rian's answers using bin are faster than using conditional evaluation - however in this context its already "fast". For readability's sake I would select the conditional evaluation due to how clear and easy it is to read, understand and modify the conditions and returns.

q)\t:10000 {[range;x] (range + 1 0) bin x}[3 5;-50+til 100]
11
q)\t:10000 3 6 bin -50+til 100
10
q)\t:10000 {$[x<3;-1;x>5;1;0]}'[-50+til 100]
75

Upvotes: 0

rianoc
rianoc

Reputation: 3651

You could look at a step dictionary which can be used in many places:

q)(`s#-0W 3 6!-1 0 1) til 10
-1 -1 -1 0 0 0 1 1 1 1

Or fill the base case:

q)-1^(`s#3 6!0 1) til 10
-1 -1 -1 0 0 0 1 1 1 1

Even better here for your exact question is to go direct to using bin:

q)3 6 bin til 10
-1 -1 -1 0 0 0 1 1 1 1

Upvotes: 3

SeanHehir
SeanHehir

Reputation: 1593

You could adapt the bin keyword which does something like what you're looking for out of the box:

q)3 5 bin 0 1 2 3 4 5 6
-1 -1 -1 0 0 1 1

If you are looking for 0 to be returned for n where x < n < y then I think you may be able to do something like:

q)f:{[range;x] (range + 1 0) bin x}
q)range35:f[3 5;]
q)range35 0N!til 10
0 1 2 3 4 5 6 7 8 9
-1 -1 -1 -1 0 1 1 1 1 1

Which returns a 0 for the number 4

Upvotes: 4

Related Questions