Rank error using if/else

Anyone know why I am getting a rank error here?  

test:([]side:())test insert stest insert bselect side:$[side=b;1;side=s;2;0] from testrank`

the if/else works fine on its own just inside the select it throws an error

You need to use the vector conditional ? instead of the atom conditional $<o:p></o:p>

<o:p> </o:p>

q)select side:?[side=b;1;?[side=s;2;0]] from test<o:p></o:p>

<o:p> </o:p>

but it would be better to do a search instead, like:<o:p></o:p>

<o:p> </o:p>

q)\ts:10000 select side:?[side=b;1;?[side=s;2;0]] from test<o:p></o:p>

100 1728<o:p></o:p>

q)\ts:10000 select ``b`s?side from test<o:p></o:p>

30 816<o:p></o:p>

<o:p> </o:p>

And significantly better for larger sets:<o:p></o:p>

q)test2:10000000?test<o:p></o:p>

q)\ts select side:?[side=b;1;?[side=s;2;0]] from test2<o:p></o:p>

198 419431120<o:p></o:p>

q)\ts select ``b`s?side from test2<o:p></o:p>

14 134218400<o:p></o:p>

<o:p> </o:p>

<o:p> </o:p>

From: personal-kdbplus@googlegroups.com [mailto:personal-kdbplus@googlegroups.com] On Behalf Of Roni Hoffman
Sent: Thursday, May 21, 2015 1:55 PM
To: personal-kdbplus@googlegroups.com
Subject: [personal kdb+] Rank error using if/else<o:p></o:p>

<o:p> </o:p>

Anyone know why I am getting a rank error here?  <o:p></o:p>

<o:p> </o:p>

test:(side:())
test insert s
test insert b

select side:$[side=b;1;side=s;2;0] from test
`rank<o:p></o:p>

<o:p> </o:p>

the if/else works fine on its own just inside the select it throws an error<o:p></o:p>


Submitted via Google Groups

Hi Roni,

Reason why you are getting rank is because it is the incorrect logic/rank for the if/else statement. If you use 0N! in your statement

you can see “01b” outputted first. 0N! can be useful here for debugging. 

select side:$[0N!side=b;1;side=s;2;0] from test

As David pointed out you should use the vector conditional, or you could even use $[;;]each x

e.g.

select side:{$[x=b;1;x=s;2;0]}each side from test

but I wouldn’t recommend it as the vector would be much faster here. 

However there is a better method for this and this also helps you out much more if you are going to have more conditions (and they follow the same search and replace requirement). This is done by creating a dictionary/map and using simple indexing.  Writing out cumulative conditions out can become tiresome, and slow. 

q)\ts  select side:?[side=b;1;?[side=s;2;0]] from test2

321 419431312

q)\ts select side:0^(bs!1 2) side from test2

79 268436224

//the 0 fills itself takes 20% of the time!!

q)\ts select side:(bs!1 2) side from test2

62 268436112

//confirm results match

q)(select side:0^(bs!1 2) side from test2)~select side:?[side=b;1;?[side=s;2;0]] from test2

1b

this mapping/indexing really becomes useful when you have more than say 2 conditions. It gives you the flexibility to replace with what you want at very good speed in short code. 

//lets make 24 letters of the alphabet be replaced with 1-24, and the rest with 0

//im not going to write out all the conditionals so make ourselves a helper function

f:{?[z;();0b;(enlist y)!enlist {(?;(=;z;enlist first y);last y;x)}[;;y] over reverse x]}

//lets make ourselves a table with more ids

q)test3:(side:10000000?`1)

q)\ts f[(2_($'.Q.a),'1+til 26),0;side;test3]

1487 301997456

q)\ts select 0^(2_((`$'.Q.a)!1+til 26)) side from test3

161 318768128

//confirm results match

q)(select 0^(2_(($'.Q.a)!1+til 26)) side from test3)~f[(2_($'.Q.a),'1+til 26),0;`side;test3]

1b

Hope this is useful,

Sean

Thanks Sean

Thanks David, that helps