Reputation: 5918
I was going through fills explanation and came across below example: i.e if there are infinities replace them with nulls and then fill them using fills.
q)fills {(x where x=0W):0N;x} 0N 2 3 0W 0N 7 0W
Output - 0N 2 3 3 3 7 7
I want to further expand this problem that if the first value in the output is Null then fill it with default value 1, for which I had written two versions of solution.
{(x where x=0N):1;x} fills {(x where x=0W):0N;x} 0N 2 3 0W 0N 20 30 0W
1^fills {(x where x=0W):0N;x} 0N 2 3 0W 0N 20 30 0W /- Output - 1 2 3 3 3 20 30 30
Which of the two is optimized version(I think it's 2nd one using fill)?
Any better/optimized version of it?
Upvotes: 1
Views: 1358
Reputation: 80372
Convert null and +/- infinity to 0:
nanInfToZero:{[x] // Converts NaN and positive/negative infinity to zero.
if [not 9h=type x;`"Error. Inputs should be 64-bit floats, cast with `float$x"];
result: {[x] (x where x in (-0w,0w)):0n;x}[x];
:0^result;
};
if [not nanInfToZero[(0n 2 3)]~(0 2 3f); `"Incorrect"];
if [not nanInfToZero[(-0w 2 3)]~(0 2 3f); `"Incorrect"];
if [not nanInfToZero[(0w 2 3)]~(0 2 3f); `"Incorrect"];
Then use fills
to fill forward.
Tested under Windows x64 and KDB v4.
Upvotes: -1
Reputation: 1697
Adding 1 to infinity transforms it to a null
q)0W 10 0N+1
0N 11 0N
To keep the orig values, and the nulls, lets subtract 1 from the resulting list
q)-1+0W 10 0N+1
0N 10 0N
Fills can accept two params (the starting digit as x if you give it two params)
q)fills 0N 10 20 0N 40
0N 10 20 20 40
q)fills[33;] 0N 10 20 0N 40
33 10 20 20 40
So putting it altogether for your requirements
q)fills[1;] -1+x+1
1 2 3 3 3 20 30 30 30 2 3 3 3 20 30 30 30 2 3 3 3 20 30 30 30 2 3 3 3 20 30 3..
HTH, Sean
Upvotes: 1
Reputation: 13657
You can always test the solutions by timing them for a large vector
q)\ts {(x where x=0N):1;x} fills {(x where x=0W):0N;x}10000000#0N 2 3 0W 0N 20 30 0W
196 553649552
q)\ts 1^fills {(x where x=0W):0N;x}10000000#0N 2 3 0W 0N 20 30 0W
190 553649216
For large vectors you should get a small improvement by only filling the first item with 1, assuming that's the only one you need defaulted to one
q)@[;0;1^]fills {(x where x=0W):0N;x}0N 2 3 0W 0N 20 30 0W
1 2 3 3 3 20 30 30
However, if you have a sequence of nulls in the beginning (not just one) then this won't help
q)@[;0;1^]fills {(x where x=0W):0N;x}0N 0N 2 3 0W 0N 20 30 0W
1 0N 2 3 3 3 20 30 30
In that case you're better off going with the 1^
on the entire vector
Upvotes: 1