[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Iterate with condition

Gábor Sebestyén

6/20/2005 10:53:00 AM

Hi,

I need but actually don't find how to iterate an iterable collection
in Java-way. It seems generally like this:

Iterator it = objs.iterator();
while (it.hasMore()) {
Object anObj = it.next();
...
}

How can I do it in Ruby? I know objs.each do |anObj| ... end but it's
not (enough) good for me. I want to use additional cycle condition
like this:

boolean b = true;
Iterator it = objs.iterator();
while (b && it.hasMore()) {
Object anObj = it.next();
...
}

What is the equivalent to this in Ruby?
Thanks,

Gábor



11 Answers

Cs. Henk

6/20/2005 11:18:00 AM

0

On Mon, Jun 20, 2005 at 07:52:30PM +0900, G?bor SEBESTY?N wrote:
> Hi,
>
> I need but actually don't find how to iterate an iterable collection
> in Java-way. It seems generally like this:
>
> Iterator it = objs.iterator();
> while (it.hasMore()) {
> Object anObj = it.next();
> ...
> }
>
> What is the equivalent to this in Ruby?

By some lingo "Java stlyle" iterators are called "external", "Ruby
style" ones are called "internal". I make this note just to separate
languages from concepts...

So, Ruby has built-in support for only for internal iterators, but ruby
also features callcc, which makes it easy to create external ones, too.

The generator package (part of the standard lib) implements this
concept.

While this approach is pretty elegant, the downside is a massive
performance loss.

Thus you might consider using a dumb solution, if there is one. Eg, a
typical case is when you want to iterate through two arrays
simultaneously -- then, unless you have huge arrays, it would be faster
to create a joint array by Array#zip or Array#transpose, and use its
each method, or just dup the arrays and shfit them.

Csaba


Tim Hunter

6/20/2005 11:33:00 AM

0

Gábor SEBESTYÉN wrote:
> How can I do it in Ruby? I know objs.each do |anObj| ... end but it's
> not (enough) good for me. I want to use additional cycle condition like
> this:
>
> boolean b = true;
> Iterator it = objs.iterator();
> while (b && it.hasMore()) {
> Object anObj = it.next();
> ...
> }

The break statement terminates a loop.

b = true
foo.each { b = do_something(); break unless b}

Sebastian Biallas

6/20/2005 11:40:00 AM

0

Gábor SEBESTYÉN wrote:
> Hi,
>
>
[..]
> boolean b = true;
> Iterator it = objs.iterator();
> while (b && it.hasMore()) {
> Object anObj = it.next();
> ...
> }
>
> What is the equivalent to this in Ruby?

You can abuse Enumerable#find for this:

objs.find do |obj|
# do something with obj

!b # return true to stop
end

I don't know wether is very rubyish ;)

> Thanks,
>
> Gábor

Sebastian

Robert Klemme

6/20/2005 12:08:00 PM

0

Timothy Hunter wrote:
> Gábor SEBESTYÉN wrote:
>> How can I do it in Ruby? I know objs.each do |anObj| ... end but it's
>> not (enough) good for me. I want to use additional cycle condition
>> like this:
>>
>> boolean b = true;
>> Iterator it = objs.iterator();
>> while (b && it.hasMore()) {
>> Object anObj = it.next();
>> ...
>> }
>
> The break statement terminates a loop.
>
> b = true
> foo.each { b = do_something(); break unless b}

return works as well if in a method

def sample
foo.each {|x| return x if do_something(x) }
end


There are other methods that may suit depending on Gabor's requirements:
#find, #select, #any?, #all? ...

What exactly do you want to do with the collection?

Kind regards

robert

Gábor Sebestyén

6/20/2005 2:31:00 PM

0


On 2005.06.20., at 14:10, Robert Klemme wrote:

> What exactly do you want to do with the collection?
>
I want to get the first N pieces of "valid" objects from a
collection. I would iterate in collection counting how many objects
were sucessfully accepted and would break the cycle if there are no
more objects or I already have my N objects. Here's my solution
(written for Rails and the collection consists of ActiveRecord objects):

cl = CustomerQueue.find(:all, :conditions => cond, :order =>
"created_at ASC")

i = 0
while i < cl.size and n > 0
c = _openChat(cl[i].customer_id, @session[:user].id)
unless c.nil?
chats << c
n = n - 1
end
end

I don't like referencing by index. That's why I asked you how to
implement this using iterator and not a simple while cycle with
indexing.

Gábor


"Never trust a computer you can't throw out a window." - Steve Wozniak

Cs. Henk

6/20/2005 2:46:00 PM

0

On Mon, Jun 20, 2005 at 11:31:09PM +0900, G?bor SEBESTY?N wrote:
>
> On 2005.06.20., at 14:10, Robert Klemme wrote:
>
> >What exactly do you want to do with the collection?
> >
> I want to get the first N pieces of "valid" objects from a
> collection. I would iterate in collection counting how many objects
> were sucessfully accepted and would break the cycle if there are no
> more objects or I already have my N objects. Here's my solution
> (written for Rails and the collection consists of ActiveRecord objects):
>
> cl = CustomerQueue.find(:all, :conditions => cond, :order =>
> "created_at ASC")
>
> i = 0
> while i < cl.size and n > 0
> c = _openChat(cl[i].customer_id, @session[:user].id)
> unless c.nil?
> chats << c
> n = n - 1
> end
> end
>
> I don't like referencing by index. That's why I asked you how to
> implement this using iterator and not a simple while cycle with
> indexing.

Maybe

cl.each_with_index { |e,i|
i < n or break
c = _openChat(e.customer_id, @session[:user].id) and chats << c
}

Csaba



Robert Klemme

6/20/2005 2:59:00 PM

0

Csaba Henk wrote:
> On Mon, Jun 20, 2005 at 11:31:09PM +0900, G?bor SEBESTY?N wrote:
>>
>> On 2005.06.20., at 14:10, Robert Klemme wrote:
>>
>>> What exactly do you want to do with the collection?
>>>
>> I want to get the first N pieces of "valid" objects from a
>> collection. I would iterate in collection counting how many objects
>> were sucessfully accepted and would break the cycle if there are no
>> more objects or I already have my N objects. Here's my solution
>> (written for Rails and the collection consists of ActiveRecord
>> objects):
>>
>> cl = CustomerQueue.find(:all, :conditions => cond, :order =>
>> "created_at ASC")
>>
>> i = 0
>> while i < cl.size and n > 0
>> c = _openChat(cl[i].customer_id, @session[:user].id)
>> unless c.nil?
>> chats << c
>> n = n - 1
>> end
>> end
>>
>> I don't like referencing by index. That's why I asked you how to
>> implement this using iterator and not a simple while cycle with
>> indexing.
>
> Maybe
>
> cl.each_with_index { |e,i|
> i < n or break
> c = _openChat(e.customer_id, @session[:user].id) and chats << c
> }

Nah, this cries for #inject!

found = collection.inject([]) do |f,x|
if check_condition(x)
f << x
break f if f.size >= 10
end
f
end

>> (0..100).inject([]){|f,x| if x%3==0 then f << x; break f if f.size ==
10 end; f}
=> [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
>> (0..10).inject([]){|f,x| if x%3==0 then f << x; break f if f.size == 10
end; f}
=> [0, 3, 6, 9]

:-)

Kind regards

robert

Cs. Henk

6/20/2005 3:06:00 PM

0

On Tue, Jun 21, 2005 at 12:00:36AM +0900, Robert Klemme wrote:
> Csaba Henk wrote:
> > Maybe
> >
> > cl.each_with_index { |e,i|
> > i < n or break
> > c = _openChat(e.customer_id, @session[:user].id) and chats << c
> > }
>
> Nah, this cries for #inject!
>
> found = collection.inject([]) do |f,x|
> if check_condition(x)
> f << x
> break f if f.size >= 10
> end
> f
> end

I see, you are right -- the counter should tick only if a "non-void"
entry is fetched.

Csaba


Gábor Sebestyén

6/20/2005 8:05:00 PM

0


On 2005.06.20., at 17:00, Robert Klemme wrote:

> Nah, this cries for #inject!
>
Wow! Perfect!
Thaaaanks! :)

Gábor

To be is to do. - Socrates
To do is to be. - Sartre
Do be do be do. - Sinatra

Gene Tani

6/20/2005 9:22:00 PM

0

i think you mean #find_all