'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.

kdb


Solution 1:[1]

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

Solution 2:[2]

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

Solution 3:[3]

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 SeanHehir
Solution 2 rianoc
Solution 3 MurrMack