From: Robert Klemme Date: 2007-05-06T23:10:04+09:00 Subject: Re: fixnum, range and array into one single loop? On 06.05.2007 15:30, Robert Klemme wrote: > On 06.05.2007 15:20, anansi wrote: >> 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? > > 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 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