Selecting values below a threshold and anchored at the left or right using Ruby NArray

88 Views Asked by At

Using NArray, is there some nifty way to create masks of arrays with values below e.g. 5, but only for runs of values anchored a the left or right side, E.g. this 1-D array:

[3, 4, 5, 7, 1, 7, 8]

would result in:

[1, 1, 0, 0, 0, 0, 0]

And this 2-D array:

[[2, 4, 5, 7, 1, 2, 3], 
 [3, 4, 5, 7, 1, 7, 8],
 [8, 1, 1, 7, 1, 7, 1]]

would result in:

[[1, 1, 0, 0, 1, 1, 1], 
 [1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1]]
1

There are 1 best solutions below

0
On BEST ANSWER
require "narray"

def anchor_mask(mask)
  idx = (mask.not).where
  y = idx/mask.shape[0]
  u = (y[0..-2].ne y[1..-1]).where
  t = [0] + (u+1).to_a + [idx.size]
  s = (0..u.size).map{|i| idx[t[i]]..idx[t[i+1]-1]}
  mask[s] = 0
  return mask
end

a = NArray[3, 4, 5, 7, 1, 7, 8]

p anchor_mask a.lt(5)
#=> NArray.byte(7):
#   [ 1, 1, 0, 0, 0, 0, 0 ]

a = NArray[[2, 4, 5, 7, 1, 2, 3],
           [3, 4, 5, 7, 1, 7, 8],
           [8, 1, 1, 7, 1, 7, 1]]

p anchor_mask a.lt(5)
#=> NArray.byte(7,3):
#   [ [ 1, 1, 0, 0, 1, 1, 1 ],
#     [ 1, 1, 0, 0, 0, 0, 0 ],
#     [ 0, 0, 0, 0, 0, 0, 1 ] ]