0

I'd like to iterate over an entire array, starting from any position. I'm not sure if there's a way to achieve this easily in Ruby, and I couldn't find any examples in the Array or Enumerator docs.

array = [0, 1, 2, 3, 4] array.each.starting_at(3) { |e| e } #=> [3, 4, 0, 1, 2] 

And also:

array.each.starting_at_reverse(3) { |e| e } #=> [3, 2, 1, 0, 4] 

2 Answers 2

2

You can use the rotate method for this. This method rotates the position of each element by n. So your examples can be done like this

array.rotate(3).each {|e| e } 

and

array.reverse.rotate(1).each {|e| e} 

Note: for the second method the parameter to rotate can be derived by finding the negative index of n. So for this the element at index 3 is at index -2 in a length 5 array.

Sign up to request clarification or add additional context in comments.

4 Comments

@user3281384 No worries. Good question!
rotate good spot. Although the each {|e| e} seem superfluous to requirements in both your examples.
ah yeah, that makes sense, my bad.
@sagarpandya82 No worries!
0

You can do this with upto and downto Fixnum's methods:

array = [0, 1, 2, 3, 4] last_index = array.size - 1 3.upto last_index do |i| puts array[i] end # => 3, 4 last_index.downto 3 do |i| puts array[i] end # => 4, 3 

PS. as speed benchmark, iteration with rotation faster

array.rotate(3).each {|e| puts e} 

benchmark:

require 'benchmark' array = Array.new(10000000) { rand(1...9) } last_index = array.size - 1 Benchmark.bm do |x| x.report 'upto' do 10000.upto last_index do |index| a = array[index] + 1; end end x.report 'downto' do last_index.downto 10000 do |index| a = array[index] + 1; end end x.report 'rotate' do array.rotate(10000).each {|e| a = e + 1 } end end # RESULTS: # user system total real # upto 0.680000 0.000000 0.680000 ( 0.681932) # downto 0.680000 0.000000 0.680000 ( 0.679752) # rotate 0.590000 0.040000 0.630000 ( 0.622901) 

but, as memory benchmark, iteration by array indexes less memory hungry, especially on big array sizes:

require 'memory_profiler' array = Array.new(10000000) { rand(1...9) } last_index = array.size - 1 { upto: -> { 10000.upto last_index do |index| a = array[index] + 1; end }, downto: -> { last_index.downto 10000 do |index| a = array[index] + 1; end }, rotate: -> { array.rotate(10000).each {|e| a = e + 1 } }, reverse_rotate: -> { array.reverse.rotate(10000).each {|e| a = e + 1 } } }.each { |desc, code| puts "#{desc.to_s} => #{MemoryProfiler.report(&code).total_allocated_memsize.to_s}" } # RESULTS (in bytes): # upto => 0 # no additional memory allocation # downto => 0 # no additional memory allocation # rotate => 80000040 # implicitly copied array 1 time # reverse_rotate => 160000080 # implicitly copied array 2 times 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.