Forum: Ruby Normal For Loop

259cde74004f3b9a61259ae81d6b225f?d=identicon&s=25 Cory Cory (cory)
on 2008-03-03 15:10
I'm new to Ruby.  Is there such thing as a C++ style (and most others)
for loop in Ruby?  What I mean by that is:

for( init, while-condition, increment ) { function-here }

I know I can do that with a while loop, but I enjoy the compactness of
the above statement.  There are many times where Ruby's for-each loops
just don't do the trick.

Also, is there anything like i++ or do I always have to do i=i+1 ?
6d9bf78ca49a017e9e3e6b0357b6c59e?d=identicon&s=25 Peter Hickman (Guest)
on 2008-03-03 15:17
(Received via mailing list)
Cory Cory wrote:
> I'm new to Ruby.  Is there such thing as a C++ style (and most others)
> for loop in Ruby?  What I mean by that is:
>
> for( init, while-condition, increment ) { function-here }
>
> I know I can do that with a while loop, but I enjoy the compactness of
> the above statement.  There are many times where Ruby's for-each loops
> just don't do the trick.
>

We would be very interested to see a loop in C that cannot be rewritten
in Ruby. Care to give us an example?

> Also, is there anything like i++ or do I always have to do i=i+1 ?
>
You can use i += 1.
97550977337c9f0a0e1a9553e55bfaa0?d=identicon&s=25 Jano Svitok (Guest)
on 2008-03-03 15:20
(Received via mailing list)
On Mon, Mar 3, 2008 at 3:10 PM, Cory Cory <cg821105@ohio.edu> wrote:
> I'm new to Ruby.  Is there such thing as a C++ style (and most others)
>  for loop in Ruby?  What I mean by that is:
>
>  for( init, while-condition, increment ) { function-here }
>
>  I know I can do that with a while loop, but I enjoy the compactness of
>  the above statement.  There are many times where Ruby's for-each loops
>  just don't do the trick.

There is 5.times {|i| } if the count is known at cycle start.
Then you have array.each {}, and the whole bunch from Enumerable
(each_with_index, select, find, map, inject, ...)
Be9f5eca2661acace327b45f8b1acabf?d=identicon&s=25 unknown (Guest)
on 2008-03-03 15:24
(Received via mailing list)
On Mon, 3 Mar 2008 23:10:09 +0900, Cory Cory <cg821105@ohio.edu> wrote:
> I'm new to Ruby.  Is there such thing as a C++ style (and most others)
> for loop in Ruby?  What I mean by that is:
>
> for( init, while-condition, increment ) { function-here }
>
> I know I can do that with a while loop, but I enjoy the compactness of
> the above statement.  There are many times where Ruby's for-each loops
> just don't do the trick.

["foo", "bar", "baz"].each_with_index {|elem, i|
  puts "#{elem} #{i}"
}


    Kristian
B33ea5c12d767bfd1253940a960274f5?d=identicon&s=25 Tim Hunter (timhunter)
on 2008-03-03 15:30
Jano Svitok wrote:
> On Mon, Mar 3, 2008 at 3:10 PM, Cory Cory <cg821105@ohio.edu> wrote:
>> I'm new to Ruby.  Is there such thing as a C++ style (and most others)
>>  for loop in Ruby?  What I mean by that is:
>>
>>  for( init, while-condition, increment ) { function-here }
>>
>>  I know I can do that with a while loop, but I enjoy the compactness of
>>  the above statement.  There are many times where Ruby's for-each loops
>>  just don't do the trick.
>
> There is 5.times {|i| } if the count is known at cycle start.
> Then you have array.each {}, and the whole bunch from Enumerable
> (each_with_index, select, find, map, inject, ...)

Not to mention Numeric#step:

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

And Integer#upto:

5.upto(10) { |i| print i, " " }
B1f06f732d86e562563db728b2875eb2?d=identicon&s=25 jwmerrill@gmail.com (Guest)
on 2008-03-03 15:30
(Received via mailing list)
On Mar 3, 9:10 am, Cory Cory <cg821...@ohio.edu> wrote:
> I'm new to Ruby.  Is there such thing as a C++ style (and most others)
> for loop in Ruby?  What I mean by that is:
>
> for( init, while-condition, increment ) { function-here }

for n in 1..10
    puts n
end

It seems more common in ruby to do things like

1.upto(10) {|n| puts n}

or

(1..10).each {|n| puts n}

If you mean that you want your condition and your increment to depend
on things that you won't know about until after the loop has been
running for a while, then yeah, you might have to use a while loop.
This doesn't seem to come up much, though.  Perhaps you could post a
specific example.

> I know I can do that with a while loop, but I enjoy the compactness of
> the above statement.  There are many times where Ruby's for-each loops
> just don't do the trick.

With a little creativity, not so many, in my experience.

> Also, is there anything like i++ or do I always have to do i=i+1 ?

i=i+1 is the way to do it.  There is some rationale for this, but I
don't remember what it is.

JM
259cde74004f3b9a61259ae81d6b225f?d=identicon&s=25 Cory Cory (cory)
on 2008-03-03 15:37
I understand that all of these for-each style loops are available, but I
don't want to always go through the entire loop, sometimes I want to
stop at some earlier condition.

I tried to do this the other night, but right now I can't find a good
example so here it goes:

a = some_array
minValue = 999999
for(i=0; i<a.length && minValue!=0; i+=1) {
   minValue = (5000 - a[i]).abs
}


This isn't the best example.  However, there are many times like the
loop above where I want to go through the whole thing, but if I find
exactly what I am looking for, I want to bail out early instead of
wasting that processing time.

Also, I sometimes may want to not actually iterate straight through, but
browse through the array in some more complex order.
97550977337c9f0a0e1a9553e55bfaa0?d=identicon&s=25 Jano Svitok (Guest)
on 2008-03-03 15:44
(Received via mailing list)
On Mon, Mar 3, 2008 at 3:29 PM, jwmerrill@gmail.com
<jwmerrill@gmail.com> wrote:
>  i=i+1 is the way to do it.  There is some rationale for this, but I
>  don't remember what it is.

IIRC, the rationale is that variables in ruby are just references to
objects, so you cannot call methods
on variables themselves. You call methods on objects they reference.
That means a call (except assignment)
cannot change the object a variable points to.

i.e. i = 3 that means, variable i points to/references object 3 of class
Fixnum.
if there was a call ++, (i++) that would mean the same as 3++. 3++
call can be written so that it returns 4
(actually it's called 3.succ), but there's no way to assign 4 back to
i. It would still point to 3. And because Fixnums are
singletons (there's only one "3" object) they are read only, so
there's no 3.succ!
B1f06f732d86e562563db728b2875eb2?d=identicon&s=25 jwmerrill@gmail.com (Guest)
on 2008-03-03 15:55
(Received via mailing list)
On Mar 3, 9:37 am, Cory Cory <cg821...@ohio.edu> wrote:
> I tried to do this the other night, but right now I can't find a good
> example so here it goes:
>
> a = some_array
> minValue = 999999
> for(i=0; i<a.length && minValue!=0; i+=1) {
>    minValue = (5000 - a[i]).abs
>
> }

What does this example do exactly?  It seems to run until it finds a
value in a that is equal to 5000, and then stop without reporting
anything.

a.detect {|n| 5000 == n}

or

a.any? {|n| 5000 == n}

See, this is actually more concise and readable, I think.

> This isn't the best example.  However, there are many times like the
> loop above where I want to go through the whole thing, but if I find
> exactly what I am looking for, I want to bail out early instead of
> wasting that processing time.
>
> Also, I sometimes may want to not actually iterate straight through, but
> browse through the array in some more complex order.

The point is not that no examples exist, but that they realistically
don't come up very much.  Get familiar with the methods in Enumerable,
Array, and Numeric.  Each time you want to write a for loop, try and
use one of those instead, and if you get stuck, ask for advice.
You're solution will almost always be more readable, and maybe 1 time
in 100 you'll need to use a while loop.

JM
C40020a47c6b625af6422b5b1302abaf?d=identicon&s=25 Stefano Crocco (crocco)
on 2008-03-03 15:59
(Received via mailing list)
Alle Monday 03 March 2008, jwmerrill@gmail.com ha scritto:
>
> See, this is actually more concise and readable, I think.
> don't come up very much.  Get familiar with the methods in Enumerable,
> Array, and Numeric.  Each time you want to write a for loop, try and
> use one of those instead, and if you get stuck, ask for advice.
> You're solution will almost always be more readable, and maybe 1 time
> in 100 you'll need to use a while loop.
>
> JM

If you want to exit the loop before all iterations are done, you can use
break.

Stefano
Fe5e1dff16dfba1e5bd28a6f1064e186?d=identicon&s=25 framefritti@gmail.com (Guest)
on 2008-03-03 16:06
(Received via mailing list)
Cory Cory ha scritto:

>    minValue = (5000 - a[i]).abs
> }
>
>
> This isn't the best example.  However, there are many times like the
> loop above where I want to go through the whole thing, but if I find
> exactly what I am looking for, I want to bail out early instead of
> wasting that processing time.

In this case you can use "break" construct  (which I, personally,
love).  For example,

minValue = 999999
a.each do |x|
  minValue = (5000-x).abs
  break if minValue==0
end

(I did not actually try it, but it should work)
>
> Also, I sometimes may want to not actually iterate straight through, but
> browse through the array in some more complex order.

In this case I'm afraid that you must resort to a while...  (BTW, I
always considered
C-style "for" as a "while" in disguise... ;-)
14ee2e1620f4c121cc25dfcd6110ebfe?d=identicon&s=25 Anton Bangratz (Guest)
on 2008-03-03 16:18
(Received via mailing list)
Attachment: signature.asc (545 Bytes)
Cory Cory wrote:
[for-loops instead of Array#each and friends]

> a = some_array
> minValue = 999999
> for(i=0; i<a.length && minValue!=0; i+=1) {
>    minValue = (5000 - a[i]).abs
> }
>

Break is your friend;
Some solutions for this example:

# No. 1
# (assuming that you are going to process the element, in this case,
# printing it to STDOUT and adding a newline):
a = [100, 200, 3000, 5000, 80000] # Arbitrary Array initialisation,
                                  # will be needed for all examples.
a.each {|i|
  break if (5000-i).abs == 0
  puts i
}
100
200
3000
    ==>nil

# No. 2
# returning an array with elements *not* meeting the condition
a.reject { |i| (5000-i).abs == 0 } # Can also be used as 'select'
                                   # with inverted condition
    ==>[100, 200, 3000, 80000]

# No. 3
# returning an array without elements > 5000
a.select { |i| i < 5000 }
    ==>[100, 200, 3000]

# No. 4
# contrived example, using #map and #compact
# Warning: Don't try this at home
a.map { |i| i < 5000 ? i : nil }.compact
    ==>[100, 200, 3000]

# No. 5
# contrived example again, this time using 'size' and artificial
# 'index'; using exact condition, so 'unless' is needed instead of
# 'if'. Using puts for 'debug' messages, or instead of processing
# values. Less readable.
a.size.times { |i|
  break unless (5000 - a[i]).abs != 0
  puts a[i]
}
100
200
3000
    ==>nil


>
> This isn't the best example.  However, there are many times like the
> loop above where I want to go through the whole thing, but if I find
> exactly what I am looking for, I want to bail out early instead of
> wasting that processing time.

That's what 'break' is for.

>
> Also, I sometimes may want to not actually iterate straight through, but
> browse through the array in some more complex order.

For Array manipulation, selection etc, refer to 'ri Array' - I can't
see how 'C-style for loops' would help there either.

t.
259cde74004f3b9a61259ae81d6b225f?d=identicon&s=25 Cory Cory (cory)
on 2008-03-03 16:24
Alright, you people have convinced me.  Break seems like a good
solution, I like that you can put a condition after it.  The last
submission seems very interested and I'm excited to learn all of these
different array functions.

Anyone know anything about "Rails for PHP Developers" book?  I have been
programming in PHP sense I was like 13, it is burned into my head.  I
like scripting in Ruby, but I'm still very uncomfortable with Rails
development.  Is that book any good?
D7463bd611f227cfb2ef4da4a978a203?d=identicon&s=25 Christopher Dicely (Guest)
on 2008-03-03 17:09
(Received via mailing list)
On Mon, Mar 3, 2008 at 6:10 AM, Cory Cory <cg821105@ohio.edu> wrote:
> I'm new to Ruby.  Is there such thing as a C++ style (and most others)
>  for loop in Ruby?  What I mean by that is:
>
>  for( init, while-condition, increment ) { function-here }

Simply put, no, Ruby has nothing that works quite like the C-style for
loop.
>
>  I know I can do that with a while loop, but I enjoy the compactness of
>  the above statement.

Usually, there is a simpler compact idiom using the iterator methods in
the
Enumerable module or specific container classes like Array if you need
something more compact than a while loop.

> There are many times where Ruby's for-each loops
> just don't do the trick.

The main looping  tehcnique in Ruby is using iterator methods. You
could make something like the C-style for loop using them, with the
caveat
that all the loop parameters have to be specified as proc objects. It
would
be something like (this is code from the top of my head):

module Kernel
  def cfor (init, condition, increment)
    init.call
    while condition.call
      yield
      increment.call
    end
  end
end

But, even if proc objects didn't make calling this a little ugly,
you really don't need it: there is generally a better more specific
way of doing things in Ruby.

For instance, in the example you give later in the thread:

> a = some_array
> minValue = 999999
> for(i=0; i<a.length && minValue!=0; i+=1) {
>   minValue = (5000 - a[i]).abs
> }

You seem to want to find the index of the first item in the array
that equals 5000 (which is what the value of i is when you bail
out) or the absolute value of 5000 minus the last item value in
the area (what minValue is if you fail to bail out).

so:

a = some_array
i = a.index(5000) || a.length
minValue = (i<a.length) ? 0 : (5000-a.last).abs

You can probably do something more elegant depending on
what you are doing with the results.

>
>  Also, is there anything like i++ or do I always have to do i=i+1 ?

You can do i+=1, i=i.succ, or i=i.next, if you prefer, but Ruby doesn't
have
the increment or decrement operators of the C family.
8209debe0ccee5d905ea2797cb94a5b0?d=identicon&s=25 Sa Mi (saverio-miroddi)
on 2011-01-15 10:52
> I tried to do this the other night, but right now I can't find a good
> example so here it goes:
>
> a = some_array
> minValue = 999999
> for(i=0; i<a.length && minValue!=0; i+=1) {
>    minValue = (5000 - a[i]).abs
> }
>
>
> This isn't the best example.  However, there are many times like the
> loop above where I want to go through the whole thing, but if I find
> exactly what I am looking for, I want to bail out early instead of
> wasting that processing time.
>
> Also, I sometimes may want to not actually iterate straight through, but
> browse through the array in some more complex order.

I have a "good" example. In my case I want to iterate a collection,
skipping a variable number of elements based on a given element.
In this case, the C for construct (counter_init, cycle_condition,) would
be useful because I wouldn't have to initialize the counter variable
outside of the scope, and I can increment the counter inside the loop.

The code is something like this:

for ( i = 0; i < elements.size; ) do
  if elements[ i ].is_a?( OneType )
    do_operation( elements[ i ] );
    i += 1;
  elsif elements[ i ].is_a?( AnotherType )
    sub_elements = []
    begin
      sub_elements << elements[ i
      i += 1;
    end while elements[ i ].is_a?( AnotherType )
    do_another_operation( sub_elements )
  else
    ...
  end
end

This example doesn't pretend to be clever/correct/well constructed, but
is a real-world case where this kind of loop would be useful.
B31e7abd14f1ceb4c4957da08933c630?d=identicon&s=25 Josh Cheek (josh-cheek)
on 2011-01-15 12:40
(Received via mailing list)
On Sat, Jan 15, 2011 at 3:52 AM, Saverio Miroddi
<saverio.pub2@gmail.com>wrote:

> > This isn't the best example.  However, there are many times like the
> be useful because I wouldn't have to initialize the counter variable
>    begin
> is a real-world case where this kind of loop would be useful.
>
> --
> Posted via http://www.ruby-forum.com/.
>
>

It is probably unwise to put different types of data all in the same
array,
but here is my attempt (relies on 1.9 Enumerable method #chunk
http://ruby-doc.org/core/classes/Enumerable.html#M001523)




# these just record what params they received
def do_operation(element)
  @do_operation ||= Array.new
  @do_operation << element
end

def do_another_operation(elements)
  @do_another_operation ||= Array.new
  @do_another_operation << elements
end

# sequences of Symbols should be considered a single element
# and Fixnums should be considered a single element
# (the data should probably not be stored like this)
elements = [1,2,:a,:b,3,4,5,9,2,:a,:b]

# chunk the data by its class
chunks = elements.chunk(&:class)
chunks.to_a # => [[Fixnum, [1, 2]], [Symbol, [:a, :b]], [Fixnum, [3, 4,
5,
9, 2]], [Symbol, [:a, :b]]]

# look at each chunk, if they are fixnums, treat them individually
# if they are symbols, treat them as a collection
chunks.each do |klass,chunk|
  if Fixnum == klass
    chunk.each { |e| do_operation e }
  elsif Symbol == klass
    do_another_operation chunk
  else
    # ...
  end
end

# What did the methods receive?
@do_operation         # => [1, 2, 3, 4, 5, 9, 2]
@do_another_operation # => [[:a, :b], [:a, :b]]
34f9c26b7a3f44bba0170dc6aab5ba2c?d=identicon&s=25 Jean Joseph (jeanjsph)
on 2013-10-22 03:06
This piece of code was done as an exercise from  Learn Ruby The Hard
Way.
I think this is more along the line of the type of for loop you are
looking for. The function's purpose may seem trivial but let me know if
this helped anyone.

def number_increaser2(max_number, increment)
  # i = 0
  numbers =  []

  for i in (0..max_number).step(increment)
    if max_number > 0
        numbers.push(i)
        puts i
        puts "Numbers now: #{numbers.join(" ")}"
            else
        puts "Max_number was too little!!\n"
        return []
          end
  end

  return numbers
end
043da5541fa61b38d9011cfaec4836ba?d=identicon&s=25 Roy Gardiner (roy-gardiner)
on 2013-10-23 20:20
jwmerrill@gmail.com wrote in post #640913:
> ... Get familiar with the methods in Enumerable,
> Array, and Numeric.  Each time you want to write a for loop, try and
> use one of those instead, and if you get stuck, ask for advice.

I am very new to Ruby, as you will see...

So far I've counted while, until, for, each, step (2 varieties), upto,
downto, each_with_index, times...

Is there a limited number (if so, is there a simple way find out how
many and what they are?), or can new methods be written indefinitely?
Aa082c8b00a50928e5860dcd70bf2368?d=identicon&s=25 tamouse m. (tamouse_m)
on 2013-10-24 08:01
(Received via mailing list)
On Oct 23, 2013, at 1:20 PM, Roy Gardiner <lists@ruby-forum.com> wrote:

> Is there a limited number (if so, is there a simple way find out how
> many and what they are?), or can new methods be written indefinitely?
>
> --
> Posted via http://www.ruby-forum.com/.

You should check out the Enumerable module:
http://ruby-doc.org/core-2.0.0/Enumerable.html
043da5541fa61b38d9011cfaec4836ba?d=identicon&s=25 Roy Gardiner (roy-gardiner)
on 2013-10-24 09:36
Thank you.

OK, I deduce from this

a.  There are any number of ways of generating a loop.
b.  It would be possible for a Ruby programmer to write new ones.

Is this correct?
14b5582046b4e7b24ab69b7886a35868?d=identicon&s=25 Joel Pearson (virtuoso)
on 2013-10-24 11:12
Yes, and you can write some very creative loops if you want, as abstract
or as precise as you like. There are some great options with
multiple-variable loops. Using blocks and yield makes for some amazing
loop options in Ruby.
043da5541fa61b38d9011cfaec4836ba?d=identicon&s=25 Roy Gardiner (roy-gardiner)
on 2013-10-24 11:32
Hmmm.  The basic principle of (just about) all programming is, as we all
know, KISS.  Because the more complicated it is

a.  the more likely there are to be errors
b.  the harder it becomes to maintain.

I fear (in absence of knowledge, I'm just starting don't forget) that
'amazing loop options' makes the writing  overly clever,
incomprehensible code too easy.  I'd love to be wrong...?
14b5582046b4e7b24ab69b7886a35868?d=identicon&s=25 Joel Pearson (virtuoso)
on 2013-10-24 11:58
I was referring to situational things like yielding multiple objects to
a loop as an array, adding an index, using yield rather than having a
staticly defined method...
043da5541fa61b38d9011cfaec4836ba?d=identicon&s=25 Roy Gardiner (roy-gardiner)
on 2013-10-24 12:11
My apologies, I was not making a personal remark. I am hopelessly
underqualified to discuss any basic, never mind advanced, features of
Ruby.

My question was general, perhaps I'll try again -- is it easy for a bad
programmer to write overly complicated code?
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.