Search code examples
arraysrubygroupingnmatrix

Ruby group non-zero numbers and sequential times


I have an array of items like so: [DateTime, value]. I want to group the items which satisfy the following conditions:

  • A sequence of 3 or more items
  • Items contain values which are > 0
  • times are sequential (increasing by 1 second)

I want to get the indices of the start and end of the sequences that meet those conditions.

E.g.

[ 
[today 10:00:00, 1],
[today 10:00:01, 1],
[today 10:00:02, 1],
[today 10:00:03, 0],
[today 10:00:04, 1],
[today 10:00:05, 1],
[today 10:00:16, 1],
[today 10:00:17, 1],
]

Should return:

[ [0,2] ]

I had a look at Daru and NMatrix but I couldn't figure out how to do sequential comparisons to do what I want.

Now I've just got a big loop that does a lot of comparisons - is there a better way to do it?


Solution

  • t = Time.now
    a = [
      [t + 0, 1],
      [t + 1, 1],
      [t + 2, 1],
      [t + 3, 0],
      [t + 4, 1],
      [t + 5, 1],
      [t + 16, 1],
      [t + 17, 1],
    ]
    
    a
    .each_with_index
    .chunk_while{
      |(x, i), (y, j)|
      x[1].positive? and
      y[1].positive? and
      x[0].to_i.next == y[0].to_i
    }
    .select{|chunk| chunk.length >= 3}
    .map{|chunk| [chunk.first[1], chunk.last[1]]}
    # => [[0, 2]]