[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

array.each restart when array is changed

Kevin Börgens

11/10/2004 10:45:00 PM

Hi!


How to restart a "each" iteration when the iterated array is changed? I do
it like this

changed=false
while (changed)
changed=false
array.each {|e|
if (today_is_christmas)
array=array+=["Hello santa claus"]
changed=true
end
}

Is there a more elegant way to do this?


Second question:
why is this not allowed

#show me the first n letters of the alphabet
('a'...'a'+gets.to_i).each{|e| puts e }

How to do it the right way?

Thanks in advance,
Kevin
17 Answers

Kevin Börgens

11/10/2004 10:52:00 PM

0

Kevin Börgens wrote:

> Hi!
>
>
> How to restart a "each" iteration when the iterated array is changed? I do
> it like this
>
> changed=false
> while (changed)
> changed=false
> array.each {|e|
> if (today_is_christmas)
> array=array+=["Hello santa claus"]
> changed=true
> end
> }

As I re-read my post, I find it a bit ambituous. It is not important that
directly after the change the iteration is restarted, it is sufficient when
it is restarted when the iteration finishes (like in the above example)

TIA,
Kevin

Ara.T.Howard

11/10/2004 11:03:00 PM

0

Shashank Date

11/11/2004 12:26:00 AM

0

Kevin Börgens wrote:
> Second question:
> why is this not allowed

Because 'a' does not automagically cast to Fixnum.
You have to do 'a'[0] to do that and .chr to get back the
character.

> #show me the first n letters of the alphabet
> ('a'...'a'+gets.to_i).each{|e| puts e }

Try this:

('a'[0]...'a'[0]+gets.to_i).each{|e| puts e.chr}

> How to do it the right way?
>
> Thanks in advance,
> Kevin

Tim Hunter

11/11/2004 12:30:00 AM

0

Kevin Börgens wrote:

> #show me the first n letters of the alphabet
> ('a'...'a'+gets.to_i).each{|e| puts e }

irb(main):006:0> alpha = 'a'
=> "a"
irb(main):007:0> n = 10
=> 10
irb(main):008:0> n.times {puts alpha; alpha = alpha.succ}
a
b
c
d
e
f
g
h
i
j
=> 10
irb(main):009:0>

Robert Klemme

11/11/2004 11:06:00 AM

0


"Shashank Date" <sdate@everestkc.net> schrieb im Newsbeitrag
news:4192B183.3070204@everestkc.net...
> Kevin Börgens wrote:
> > Second question:
> > why is this not allowed
>
> Because 'a' does not automagically cast to Fixnum.
> You have to do 'a'[0] to do that and .chr to get back the
> character.
>
> > #show me the first n letters of the alphabet
> > ('a'...'a'+gets.to_i).each{|e| puts e }
>
> Try this:
>
> ('a'[0]...'a'[0]+gets.to_i).each{|e| puts e.chr}

>> (?a ... ?a+10).each {|c| puts c.chr}
a
b
c
d
e
f
g
h
i
j
=> 97...107

Regards

robert

Carlos

11/11/2004 12:23:00 PM

0

[Kevin Börgens <kevin@boergens.de>, 2004-11-10 23.48 CET]
> How to restart a "each" iteration when the iterated array is changed? I do
> it like this
>
> changed=false
> while (changed)
> changed=false
> array.each {|e|
> if (today_is_christmas)
> array=array+=["Hello santa claus"]
> changed=true
> end
> }

array.each do |e|
if (today_is_christmas)
array += ["Hello"]
retry
end
end

Beware of infinite loops.

> Second question:
> why is this not allowed
>
> #show me the first n letters of the alphabet
> ('a'...'a'+gets.to_i).each{|e| puts e }
>
> How to do it the right way?

(?a ... ?a + gets.to_i).each do |e| puts e.chr end

letter='a'; gets.to_i.times do puts letter; letter=letter.succ end

You have several possibilities.

Good luck.

--


Bill Atkins

11/11/2004 12:49:00 PM

0

How does this work? Does 'retry' recall the method associated with its block?

Bill

On Thu, 11 Nov 2004 21:23:08 +0900, Carlos <angus@quovadis.com.ar> wrote:
> [Kevin Börgens <kevin@boergens.de>, 2004-11-10 23.48 CET]
> array.each do |e|
> if (today_is_christmas)
> array += ["Hello"]
> retry
> end
> end



Robert Klemme

11/11/2004 12:52:00 PM

0


"Kevin Börgens" <kevin@boergens.de> schrieb im Newsbeitrag
news:2vfjurF2ljhdfU1@uni-berlin.de...
> Hi!
>
>
> How to restart a "each" iteration when the iterated array is changed? I
do
> it like this
>
> changed=false
> while (changed)
> changed=false
> array.each {|e|
> if (today_is_christmas)
> array=array+=["Hello santa claus"]

This is sufficient:
array += +=["Hello santa claus"]

> changed=true
> end
> }
>
> Is there a more elegant way to do this?

I would not change the array in place while iterating. Without more
knowledge about your scenario I'd do this:

added = []

begin
added.clear

array.each do |e|
if (today_is_christmas)
added << "Hello santa claus"
end
end

array.concat added
end until added.empty?


If you want to ensure, that each element is traversed only once, a queue
approach is better:

queue = array.dup

until queue.empty?
e = queue.shift

if today_is_christmas(e)
x = "Hello santa claus"
queue << x
array << x
end
end

This is much more performant because with the other solution you end up
running through the same array members over and over again.

Are you doing some kind of BFS?

Kind regards

robert

Florian Gross

11/11/2004 1:36:00 PM

0

Kevin Börgens wrote:

> #show me the first n letters of the alphabet
> ('a'...'a'+gets.to_i).each{|e| puts e }
>
> How to do it the right way?

I would just do ('a' .. 'z').to_a.first(gets.to_i)

Carlos

11/11/2004 1:36:00 PM

0

[Bill Atkins <batkins57@gmail.com>, 2004-11-11 13.49 CET]
> > array.each do |e|
> > if (today_is_christmas)
> > array += ["Hello"]
> > retry
> > end
> > end
> How does this work? Does 'retry' recall the method associated with its block?

Yes, and re-evaluates its arguments (if any).

Inside a method, it seems to recall the method (re-evaluating arguments)
only if the method has a block, altough you are not inside it. Didn't test
that much.

def repeat (what, test_until)
retry if !test_until
end

s = ""
repeat(s << "x", s.length > 5)
puts s

retry.rb:2:in `repeat': retry outside of rescue clause (LocalJumpError)
from retry.rb:6

But:

def repeat (what, test_until)
retry if !test_until
end

s = ""
repeat(s << "x", s.length > 5) {} # <-- note block
puts s

#-> xxxxxx

Greetings.