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