1

I have this code and I don't know why it doesn't give me the correct answer

list = [1] 
a = [0,0,2,3,4]

for n in a
  if n!= 0
    list.push(n)
    a.delete(n)
  end
end 

p list => [1,2,4]
p a => [0,0,3]

I don't understand why number didn't get added to list. When I tried to only use 'push' and not 'a.delete' I got the correct answers

list = [1,2,3,4]
a = [0,0,2,3,4]

What is going on?

2
  • 2
    You should do a little better job at explaining what you want and why you don't like what you get. Commented May 29, 2013 at 21:16
  • 1
    Remember, you should accept answers that solve your questions. Commented May 29, 2013 at 21:26

2 Answers 2

4

Rule number one of iterating collections: don't change the collection you're currently iterating!.

A quick fix would be to iterate a copy of the collection.

list = [1] 
a = [0,0,2,3,4]

for n in a.dup # here, a copy
  if n!= 0
    list.push(n)
    a.delete(n)
  end
end 

list # => [1, 2, 3, 4]
a # => [0, 0]
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks but do you have any idea why the 3 was just skipped?
@RubyLovely has posted the explanation in his answer.
@SergioTulentsev is this list # => [1, 2, 3, 4] automatically in your editor or you do edit this way? As I am running ST2 where output comes in different window, and I need to copy there from and paste it to here,which causes slower posting :)
@RubyLovely: Yes, textmate inserts output for me. That's why I post so fast :)
@AGS: that's my question! :)
|
2

see the output carefully:

list = [1] 
a = [0,0,2,3,4]

for n in a
  if n!= 0
    list.push(n)
    a.delete(n)
    p list,a
  end
end 

Output:

[1, 2]
[0, 0, 3, 4]
[1, 2, 4]
[0, 0, 3]

So when your loop deleted 2, which was in the 3rd item before deletion, 3 comes into that position. And as the loop completed the 3rd item processing,it will jump to the take next item from the collection,which is 4. This is how item 3 will be skipped. As after deletion all your item will be shifted from right to left. Look below for more clarity to see what is going on inside the loop and state of collection a after each delete.

list = [1] 
a = [0,0,2,3,4]

for n in a
  if n!= 0
    p n
    i = a.find_index(n)
    list.push(n)
    a.delete(n)
    p a[i]
    p "-" *8
  end
end 

output:

2
3
"--------"
4
nil
"--------"

5 Comments

Your answer could benefit greatly from a couple of pseudo-graphic illustrations of the process.
@RubyLovely: I posted the comment before you added that last paragraph.
@SergioTulentsev I have given the intermediate outputs also.
Wasn't me, if you're interested. :) I get some random downvotes too.
@RubyLovely: I don't upvote just to balance somebody's downvote (and you shouldn't too). But you have a good answer, so here's a +1 from me :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.