Iterate with condition

G

Gábor SEBESTYÉN

Hi,

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

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

How can I do it in Ruby? I know objs.each do |anObj| ... end but it's =20=

not (enough) good for me. I want to use additional cycle condition =20
like this:

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

What is the equivalent to this in Ruby?
Thanks,

G=E1bor
 
C

Csaba Henk

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
 
T

Timothy Hunter

Gábor SEBESTYÉN said:
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}
 
S

Sebastian Biallas

Gábor SEBESTYÉN said:
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
 
R

Robert Klemme

Timothy said:
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

Gábor SEBESTYÉN

--Apple-Mail-1--763269775
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
charset=ISO-8859-1;
delsp=yes;
format=flowed


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

cl =3D CustomerQueue.find:)all, :conditions =3D> cond, :eek:rder =
=3D> =20
"created_at ASC")

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

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

G=E1bor


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


--Apple-Mail-1--763269775--
 
C

Csaba Henk

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, :eek:rder =>
"created_at ASC")

i = 0
while i < cl.size and n > 0
c = _openChat(cl.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
 
R

Robert Klemme

Csaba said:
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, :eek:rder =>
"created_at ASC")

i = 0
while i < cl.size and n > 0
c = _openChat(cl.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
 
C

Csaba Henk

Csaba said:
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

Gábor SEBESTYÉN

--Apple-Mail-1--743229511
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
charset=ISO-8859-1;
format=flowed


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

G=E1bor

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


--Apple-Mail-1--743229511--
 
S

Sebastian Biallas

Gene said:
i think you mean #find_all

No, I meant #find. #find_all always iterates all elements, so it's as
(un)usable as #each in this case.

Sebastian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,173
Messages
2,570,939
Members
47,484
Latest member
JackRichard

Latest Threads

Top