Looping through an array with step

36,383

Solution 1

Ranges have a step method which you can use to skip through the indexes:

(0..array.length - 1).step(2).each do |index|
  value_you_care_about = array[index]
end

Or if you are comfortable using ... with ranges the following is a bit more concise:

(0...array.length).step(2).each do |index|
  value_you_care_about = array[index]
end

Solution 2

array.each_slice(n) do |e, *_|
  value_i_care_about = e
end

Solution 3

Just use step() method from Range class which returns an enumerator

(1..10).step(2) {|x| puts x}

Solution 4

We can iterate while skipping over a range of numbers on every iteration e.g.:

1.step(10, 2) { |i| print "#{i} "}

http://www.skorks.com/2009/09/a-wealth-of-ruby-loops-and-iterators/

So something like:

array.step(n) do |element|
  # process element
end
Share:
36,383

Related videos on Youtube

baash05
Author by

baash05

Under the hood, we all want to know more. We are here to learn through our life, to be more than when we started out. We joined StackOverflow to learn and to share. Who am I? About me? I am a father of two amazing children: bright happy and filled with energy. I am a husband, of one amazing woman. I say I like to run, but I don't do it, I say I love to code, and I do it almost as often as I can. I used to do WingChun, and in some ways it defines who I turned into. A man who loves simple logic. Low level where and when I can. I like to find the rules and then twist them about, bending but never break them.

Updated on November 01, 2020

Comments

  • baash05
    baash05 over 3 years

    I want to look at every n-th elements in an array. In C++, I'd do this:

    for(int x = 0; x<cx; x+=n){
        value_i_care_about = array[x];
        //do something with the value I care about.  
    }
    

    I want to do the same in Ruby, but can't find a way to "step". A while loop could do the job, but I find it distasteful using it for a known size, and expect there to be a better (more Ruby) way of doing this.

    • baash05
      baash05 over 11 years
      Nothing about the step could be found :) each.. or for loop is easy to find.. I want to do every 5th or 10th or 9th element in the array
    • Mischa
      Mischa over 11 years
      Benjamin's answer is incorrect. You should look at Levi's or David's answer.
    • Mischa
      Mischa over 11 years
      Yes, it makes sense that 1.step(3, 2) gives 1 and 3. In this code the step is 2, so the second element gets skipped. Which leaves you with 1 and 3.
    • baash05
      baash05 over 11 years
      Yeah I see how it works now. Thanks all.
    • mrbrdo
      mrbrdo over 11 years
      By the way, this has nothing to do with Rails, it's a Ruby question.
  • baash05
    baash05 over 11 years
    You missed the bit about the step. That was the important bit.
  • bdeonovic
    bdeonovic over 11 years
    Just feeling a bit under the weather tonight =D
  • Mischa
    Mischa over 11 years
    This doesn't work. Array doesn't have a step method, so you will get "Undefined method for step". 1.step(10,2) does work, but that doesn't iterate over an array. Levi has the correct answer.
  • baash05
    baash05 over 11 years
    had to vote you down... if n is 1000 then and I've got 10000 elements I've just done 10000 if's I didn't need to to get 10 elements.
  • baash05
    baash05 over 11 years
    Yeah.. but in Ben's defence.. it was enough to figure it out. And Levi's doesn't iterate over the array either. Both excellent answers.
  • doesterr
    doesterr over 11 years
    I was just wondering why it got downvoted.. thanks for letting me know
  • doesterr
    doesterr over 11 years
    Of course you're absolutely right with that. The negative impact gets larger, the bigger your step size is. If you're as curious about it as I was just now, see the significant benchmark results in this gist: gist.github.com/3936015
  • baash05
    baash05 over 11 years
    excellent search dave. Anytime a compare is in the loop it's run each time.. if you can get if's out of your loop it runs faster. I like to watch my cycles and let the .... take care of them selves.
  • doesterr
    doesterr over 11 years
    then, I'll just replace my ifs with unless... jk ;)
  • 244an
    244an over 10 years
    You can use (0...array.length) instead of (0..array.length - 1)
  • baash05
    baash05 over 9 years
    nice. Not in love with the idea of creating a range of a million where an int would do the job in c++.. but cool
  • Mark Thomas
    Mark Thomas over 8 years
    Um, maybe, but in this case completely unnecessary. Just use the block form of select: [1, 2, 3, 4, 5, 6, 7].select(&:odd?)