# Fixnum, range and array into one single loop?

**URL:** <https://www.ruby-forum.com/t/fixnum-range-and-array-into-one-single-loop/103466>\
**Category:** Ruby\
**Created:** [May 6, 2007, 3:25pm UTC](https://www.ruby-forum.com/t/fixnum-range-and-array-into-one-single-loop/103466 "2007-05-06T15:25:38Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![anansi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/9fc348/32.png) [@anansi](https://www.ruby-forum.com/u/anansi)\
**Post date:** [May 6, 2007, 3:25pm UTC](https://www.ruby-forum.com/t/fixnum-range-and-array-into-one-single-loop/103466/1 "2007-05-06T15:25:38Z")

</div>

Hi,  
I’m struggeling with writing a little script. It has a loop just e.g.  
like this:

for x in 1…10 do  
begin  
puts “#{x}”  
end

The userinput is the loop count (so above the userinput would have been  
1…10): but now this userinput can be a fixnum like 12 or 36 or it can  
be a range like 1…10 or 24…84 or an array like [23,41,35,63] and for  
every 3 different input kinds the loop shall do the same.

Like in this example:

If userinput is just fixnum 11 it just prints 11 on the screen, is it a  
range from 1…10 all numbers from 1…10 shall be printed and for an  
array all single numbers stored in the array…you know what I mean. The  
actual routine doesn’t print anything it’s just about I have to process  
numbers which can the user give in, in three different ways and I was  
wondering if it is possible to build this into one single loop and not  
three different ones?

–  
greets

```
                        (
                        )
                     (
              /\ .-"""-. /\
             //\\/ ,,, \//\\
             |/\| ,;;;;;, |/\|
             //\\\;-"""-;///\\
            // \/ . \/ \\
           (| ,-_| \ | / |_-, |)
             //` __\.-.-./__ `\\
            // /.-(() ())-.\ \\
           (\ |) '---' (| /)
            ` (| |) `
      jgs \) (/

```

one must still have chaos in oneself to be able to give birth to a  
dancing star

---

<div class="post-metadata">

**Author:** ![anansi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/9fc348/32.png) [@anansi](https://www.ruby-forum.com/u/anansi)\
**Post date:** [May 6, 2007, 3:36pm UTC](https://www.ruby-forum.com/t/fixnum-range-and-array-into-one-single-loop/103466/2 "2007-05-06T15:36:39Z")

</div>

On 06.05.2007 15:20, anansi wrote:

> 1…10): but now this userinput can be a fixnum like 12 or 36 or it can  
> wondering if it is possible to build this into one single loop and not  
> three different ones?

How about

def my\_loop(x,&b)  
case x  
when /\A\d+\z/  
x.to\_i.times(&b)  
when /\A(\d+)…(\d+)\z/  
($1.to\_i … $2.to\_i).each(&b)  
when /\A[\s\*\d+\s\*(?:,\s\*\d+\s\*)\*]\z/  
eval(x).each(&b)  
else  
raise ArgumentError, “Don’t know what to do with: #{x}”  
end  
end

> > my\_loop(“5”) {|x| p x}  
> > 0  
> > 1  
> > 2  
> > 3  
> > 4  
> > =\> 5
> 
> > my\_loop(“1…5”) {|x| p x}  
> > 1  
> > 2  
> > 3  
> > 4  
> > 5  
> > =\> 1…5
> 
> > my\_loop("[5,3,2]") {|x| p x}  
> > 5  
> > 3  
> > 2  
> > =\> [5, 3, 2]
> 
> > my\_loop(“1,2”) {|x| p x}  
> > ArgumentError: Don’t know what to do with: 1,2  
> > from (irb):10:in `my\_loop’  
> > from (irb):16  
> > from :0
> 
> >

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![anansi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/9fc348/32.png) [@anansi](https://www.ruby-forum.com/u/anansi)\
**Post date:** [May 6, 2007, 3:40pm UTC](https://www.ruby-forum.com/t/fixnum-range-and-array-into-one-single-loop/103466/3 "2007-05-06T15:40:39Z")

</div>

anansi wrote:

> been 1…10): but now this userinput can be a fixnum like 12 or 36 or  
> and I was wondering if it is possible to build this into one single  
> loop and not three different ones?

Assuming that userinput can only be a Range, Array, or Fixnum…both  
Range and Array have an each method. Test userinput to see if it  
responds to :each. If it does, you’re golden. If it doesn’t, it’s a  
Fixnum. Make an array from the Fixnum by calling Array(). Now iterate  
over the result using :each. (This is untested but it’ll give you an  
idea of what to do.)

userinput = Array(userinput) unless userinput.respond\_to? :each  
userinput.each do |x|  
puts x  
end

P.S. the puts method converts its argument to a string. You don’t need  
to use “#{x}”.

---

<div class="post-metadata">

**Author:** ![anansi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/9fc348/32.png) [@anansi](https://www.ruby-forum.com/u/anansi)\
**Post date:** [May 6, 2007, 4:10pm UTC](https://www.ruby-forum.com/t/fixnum-range-and-array-into-one-single-loop/103466/4 "2007-05-06T16:10:42Z")

</div>

On 06.05.2007 15:30, Robert K. wrote:

> > The userinput is the loop count (so above the userinput would have  
> > process numbers which can the user give in, in three different ways  
> > ($1.to\_i … $2.to\_i).each(&b)  
> > 2
> > 
> > > my\_loop("[5,3,2]") {|x| p x}
> 
> Kind regards
> 
> ```
> robert
> 
> ```

more elegant:

def my\_loop(x,&b)  
case x  
when /\A\d+\z/  
1 … x.to\_i  
when /\A(\d+)…(\d+)\z/  
($1.to\_i … $2.to\_i)  
when /\A[\s\*\d+\s\*(?:,\s\*\d+\s\*)\*]\z/  
eval(x)  
else  
raise ArgumentError, “Don’t know what to do with: #{x}”  
end.each(&b)  
end

more modular:

def my\_enum(x,&b)  
case x  
when /\A\d+\z/  
1 … x.to\_i  
when /\A(\d+)…(\d+)\z/  
($1.to\_i … $2.to\_i)  
when /\A[\s\*\d+\s\*(?:,\s\*\d+\s\*)\*]\z/  
eval(x)  
else  
raise ArgumentError, “Don’t know what to do with: #{x}”  
end  
end

robert

---

<div class="post-metadata">

**Author:** ![anansi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/9fc348/32.png) [@anansi](https://www.ruby-forum.com/u/anansi)\
**Post date:** [May 6, 2007, 4:50pm UTC](https://www.ruby-forum.com/t/fixnum-range-and-array-into-one-single-loop/103466/5 "2007-05-06T16:50:46Z")

</div>

Hi thank you both 🙂

I took Tim’s answer because it’s faster and much smaller and my loop had  
some timeout-problems with the case-when method to solve it.

Tim H. wrote:

> > The userinput is the loop count (so above the userinput would have  
> > process numbers which can the user give in, in three different ways
> 
> userinput = Array(userinput) unless userinput.respond\_to? :each  
> userinput.each do |x|  
> puts x  
> end
> 
> P.S. the puts method converts its argument to a string. You don’t need  
> to use “#{x}”.

–  
greets

```
                        (
                        )
                     (
              /\ .-"""-. /\
             //\\/ ,,, \//\\
             |/\| ,;;;;;, |/\|
             //\\\;-"""-;///\\
            // \/ . \/ \\
           (| ,-_| \ | / |_-, |)
             //` __\.-.-./__ `\\
            // /.-(() ())-.\ \\
           (\ |) '---' (| /)
            ` (| |) `
      jgs \) (/

```

one must still have chaos in oneself to be able to give birth to a  
dancing star
