# Changes to x within x.each()

**URL:** <https://www.ruby-forum.com/t/changes-to-x-within-x-each/96513>\
**Category:** Ruby\
**Created:** [June 29, 2006, 5:20am UTC](https://www.ruby-forum.com/t/changes-to-x-within-x-each/96513 "2006-06-29T05:20:32Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![elyod\_72](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ed655f/32.png) [@elyod\_72](https://www.ruby-forum.com/u/elyod_72)\
**Post date:** [June 29, 2006, 5:20am UTC](https://www.ruby-forum.com/t/changes-to-x-within-x-each/96513/1 "2006-06-29T05:20:32Z")

</div>

Does Ruby have defined behavior for ‘each’ in the following:

```
x.each do |obj|
    ...
    x.change() # This may add or remove objects from x
end

```

Cases:

1. Adding or removing objects ‘before’ obj.
2. Adding or removing objects ‘after’ obj.

I’m primarily interested when x is an array.

---

<div class="post-metadata">

**Author:** ![elyod\_72](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ed655f/32.png) [@elyod\_72](https://www.ruby-forum.com/u/elyod_72)\
**Post date:** [June 29, 2006, 6:52am UTC](https://www.ruby-forum.com/t/changes-to-x-within-x-each/96513/2 "2006-06-29T06:52:23Z")

</div>

On Jun 28, 2006, at 11:20 PM, Jim V. Tess wrote:

> I’m primarily interested when x is an array.
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

As far as I know theres not explicitly defined behavior, but I  
believe 2) works as you might expect.

---

<div class="post-metadata">

**Author:** ![elyod\_72](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ed655f/32.png) [@elyod\_72](https://www.ruby-forum.com/u/elyod_72)\
**Post date:** [June 29, 2006, 6:55am UTC](https://www.ruby-forum.com/t/changes-to-x-within-x-each/96513/3 "2006-06-29T06:55:32Z")

</div>

On 6/29/06, Jim V. Tess [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’m primarily interested when x is an array.

From experience Ruby keeps an array index to do each, so if something  
inserted after obj it’ll work, but something before will cause each to  
get obj twice.

---

<div class="post-metadata">

**Author:** ![elyod\_72](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ed655f/32.png) [@elyod\_72](https://www.ruby-forum.com/u/elyod_72)\
**Post date:** [June 29, 2006, 5:27pm UTC](https://www.ruby-forum.com/t/changes-to-x-within-x-each/96513/4 "2006-06-29T17:27:42Z")

</div>

On 29/06/06, Phillip H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> From experience Ruby keeps an array index to do each, so if something  
> inserted after obj it’ll work, but something before will cause each to  
> get obj twice.

Yep. You can see this in the ‘why do only half the elements from my  
array get deleted?’ problem:

array = %w[a b c d e f g h i j k]  
array.each do |e|  
array.delete(e)  
end  
array # =\> [“b”, “d”, “f”, “h”, “j”]

Paul.

---

<div class="post-metadata">

**Author:** ![elyod\_72](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ed655f/32.png) [@elyod\_72](https://www.ruby-forum.com/u/elyod_72)\
**Post date:** [June 29, 2006, 9:16am UTC](https://www.ruby-forum.com/t/changes-to-x-within-x-each/96513/5 "2006-06-29T09:16:32Z")

</div>

2006/6/29, Phillip H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> From experience Ruby keeps an array index to do each, so if something  
> inserted after obj it’ll work, but something before will cause each to  
> get obj twice.

Personally I wouldn’t rely on this behavior though. Changing a  
collection while iterating it often leads to undefined behavior.  
Personally I’d rather choose an approach that either copies the  
collection or defers the changes to after the iteration. Alternatively  
with an array iterate explicitely with for and using an array index.

ar = ar.inject([]) {|copy, el|  
case x  
when “add”  
then copy \<\< el \<\< “bar”  
when “remove”  
then copy  
else  
copy \<\< el  
end  
end

Kind regards

robert
