# A loop within another loop

**URL:** <https://www.ruby-forum.com/t/a-loop-within-another-loop/81720>\
**Category:** Ruby\
**Created:** [January 11, 2007, 10:40pm UTC](https://www.ruby-forum.com/t/a-loop-within-another-loop/81720 "2007-01-11T22:40:52Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![eddiewould](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/b5e925/32.png) [@eddiewould](https://www.ruby-forum.com/u/eddiewould)\
**Post date:** [January 11, 2007, 10:40pm UTC](https://www.ruby-forum.com/t/a-loop-within-another-loop/81720/1 "2007-01-11T22:40:52Z")

</div>

Hi. Hopefully you will see the code and see what I’m trying to do, and  
see the problem. The loop seems messy, but my method to help with eye  
strain is to match up the do-end’s down an imaginary column… ie:

array.each # do # |i|  
puts i # # \<-imaginary column  
# end #

##### So here’s the code.

def foo(argument1, argument2) #1  
user = [2,5]

user.each do |bar|  
output = [] #2  
argument1.each do |i| #3

if i.parent.id == bar.id #4  
output \<\< i.parent.name  
end  
end

argument2.each do |i|  
if i.parent.id == bar.id  
output \<\< i.name  
end  
end  
return output  
end

Comments:  
#1 - argument comes in as arrays  
#2 - let’s setup the var that will return the array of collected data  
#3 - i think this is where the problem may lie.  
#4 - parent is an acts\_as\_tree method inside rails, just grabs the  
parant.  
notice how i call the iterating variable ‘bar’ inside this new  
loop…is this legal?

My intuition tells me there’s probably a better method to do this. Any  
comments, suggestions would be appreciated.

Dominic

---

<div class="post-metadata">

**Author:** ![eddiewould](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/b5e925/32.png) [@eddiewould](https://www.ruby-forum.com/u/eddiewould)\
**Post date:** [January 12, 2007, 1:19pm UTC](https://www.ruby-forum.com/t/a-loop-within-another-loop/81720/2 "2007-01-12T13:19:25Z")

</div>

Are you sure your code does what you want? It looks like your  
“user.each” block returns after the first iteration and never gets to  
the second one. It might help if you formatted your code in a more  
conventional way in your post.

---

<div class="post-metadata">

**Author:** ![eddiewould](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/b5e925/32.png) [@eddiewould](https://www.ruby-forum.com/u/eddiewould)\
**Post date:** [January 19, 2007, 4:29pm UTC](https://www.ruby-forum.com/t/a-loop-within-another-loop/81720/3 "2007-01-19T16:29:32Z")

</div>

Dominic S. wrote:

> def foo(argument1, argument2) #1
> 
> #2 - let’s setup the var that will return the array of collected data

First, your code is missing an end. Second, making the end to the block  
start is easy with the standard convention

(with the missing end added in)

def foo(argument1, argument2) #1  
user = [2,5]

user.each do |bar|  
output = [] #2  
argument1.each do |i| #3  
if i.parent.id == bar.id #4  
output \<\< i.parent.name  
end  
end  
end

argument2.each do |i|  
if i.parent.id == bar.id  
output \<\< i.name  
end  
end

output  
end

This is infinitely easier (to me, and 99.9% of programmers) than moving  
the end out to match the do. Do you find this hard to read? You seem  
to have no problem matching the end to its matching if.

---

<div class="post-metadata">

**Author:** ![eddiewould](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/b5e925/32.png) [@eddiewould](https://www.ruby-forum.com/u/eddiewould)\
**Post date:** [January 19, 2007, 4:31pm UTC](https://www.ruby-forum.com/t/a-loop-within-another-loop/81720/4 "2007-01-19T16:31:39Z")

</div>

On 1/11/07, Mike H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ##### So here’s the code.
> > 
> > end  
> > Comments:
> > 
> > Dominic
> 
> First, your code is missing an end. Second, making the end to the block  
> start is easy with the standard convention
> 
> This is infinitely easier (to me, and 99.9% of programmers) than moving  
> the end out to match the do. Do you find this hard to read? You seem  
> to have no problem matching the end to its matching if.

1. The main question: is this legal - yes, it’s perfectly legal, it’s  
one of the blocks’ features. The blocks are closures, i.e. they keep  
they outer context. This is used when you pass a block between  
functions:

def fun2  
yield 10  
end

def fun1  
a= 5  
puts fun2 do |i| # yield 10 will set i=10  
i + a # here block has access to a even though it is called from  
fun2  
end # =\> 15  
end

1. few changes to the code:  
(I changed bar.id to just bar - it seems to me that’s what you want)

def foo(argument1, argument2)  
user = [2,5]  
output = []  
user.each do |bar|  
output += argument1.select{|i| i.parent.id == bar}.map{|i|  
i.parent.name}  
output += argument2.select{|i| i.parent.id == bar}.map{|i| i.name}  
end  
output  
end

see Enumerable#select, Enumerable#map for explanation.  
shortly: “from argument1 array select those that fulfill the condition  
and for each of them get i.parent.name”
