Remove leading zero elements from array in Ruby

Viewed 638

I have an array like this:

a = [0, 0, 1, 0, 1, 1, 0]

I would like to remove the leading 0 elements to get this:

a = [1, 0, 1, 1, 0]

What's the best way to do this in Ruby? I have come up with a solution, but it doesn't feel as elegant as it could be:

count = 0
a.each do |element|
  break if element != 0
  count += 1
end
a = a[count..-1]

I feel like there might be a clean one-liner for this.

4 Answers

I would use:

 [0, 0, 1, 0, 1, 1, 0].drop_while(&:zero?)
 #=> [1, 0, 1, 1, 0]

For speed, I'd put my money on the following.

def drop_leading_zeros(arr)
  i = arr.index(1)
  i.nil? ? arr : arr[i..-1]
end
drop_leading_zeros [0, 0, 1, 0, 1, 1, 0]  #=> [1, 0, 1, 1, 0] 
drop_leading_zeros [0, 0, 0, 0, 0, 0, 0]  #=> [] 

Let's do a benchmark.

require 'fruity'

def test(n)
  arr = Array.new(n-1, 0) << 1
  puts
  compare do
    matt        { a = arr.dup; a.drop_while { |x| x == 0} }
    spickermann { a = arr.dup; a.drop_while(&:zero?) }
    Jürgen      { a = arr.dup; a.shift until a[0] != 0; a }
    Cary        { a = arr.dup; i = a.index(1); i.nil? ? a : a[i..-1] }
  end
end

test(n) compares the four calculations for an array of size n whose last element equals 1 and all other elements equal 0. I've included a = arr.dup to each code snippet because some some would mutate arr if that was not done.

test(3)
Running each test 16384 times. Test will take about 1 second.
Jürgen is faster than matt by 30.000000000000004% ± 10.0%
matt is similar to Cary
Cary is similar to spickermann
test(10)
Running each test 8192 times. Test will take about 1 second.
Cary is faster than Jürgen by 30.000000000000004% ± 10.0%
Jürgen is faster than matt by 19.999999999999996% ± 10.0%
matt is faster than spickermann by 10.000000000000009% ± 10.0%
test(1_000)
Running each test 512 times. Test will take about 2 seconds.
Cary is faster than Jürgen by 5x ± 0.1
Jürgen is faster than matt by 10.000000000000009% ± 1.0%
matt is similar to spickermann
test(10_000)
Running each test 64 times. Test will take about 2 seconds.
Cary is faster than Jürgen by 6x ± 0.1
Jürgen is faster than matt by 10.000000000000009% ± 1.0%
matt is similar to spickermann
test(100_000)
Running each test 4 times. Test will take about 1 second.
Cary is faster than Jürgen by 6x ± 0.1
Jürgen is faster than matt by 10.000000000000009% ± 1.0%
matt is similar to spickermann
test(1_000_000)
Running each test once. Test will take about 3 seconds.
Cary is faster than Jürgen by 6x ± 0.1
Jürgen is faster than matt by 10.000000000000009% ± 1.0%
matt is similar to spickermann
Related