Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Array.delete inside Array.each not delete all items?

Tags:

arrays

ruby

I am new to Ruby and I wrote a very simple application to print the days of week and then delete one day in a loop:

def print_days(days)
    days.each do |day|
        print "The day of the week is: #{day}\n"
        days.delete(day)
        print "\n*****************************************************\n"
        print days
        print "\n*****************************************************\n"
    end
end

wd = %w[Monday Tuesday Wednesday Thursday Friday Saturday Sunday]

print print_days(wd

This gives the following output when run. Can anyone explain me why Tuesday, Thursday and Saturday are skipped when I am deleting each element sequentially and the array shows them being there? You can run this simple code at your setup:

The day of the week is: Monday

*****************************************************
["Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
*****************************************************
The day of the week is: Wednesday

*****************************************************
["Tuesday", "Thursday", "Friday", "Saturday", "Sunday"]
*****************************************************
The day of the week is: Friday

*****************************************************
["Tuesday", "Thursday", "Saturday", "Sunday"]
*****************************************************
The day of the week is: Sunday

*****************************************************
["Tuesday", "Thursday", "Saturday"]
*****************************************************
["Tuesday", "Thursday", "Saturday"]
like image 462
Qufr kaifi Avatar asked Nov 20 '25 01:11

Qufr kaifi


2 Answers

You are deleting elements from the array while you are iterating through it, invalidating the iterator.

You could try

   until (days.empty?) 
       day = days.shift
       print "The day of the week is: #{day}\n"
   end

or

   days.each{|day| print "The day of the week is: #{day}\n"}
   days.clear
like image 80
AShelly Avatar answered Nov 21 '25 13:11

AShelly


You are modifying the array during the iteration of all the elements. Internally the each method is keeping the index of the last item it yielded to your block. This is basically invalidating the iterator. Other languages would throw an exception for you.

Ruby does not.

So on the first time through it yields the element at index 0

Then you delete the element at index 0

Then the next time through the it yields the element at index 1, which basically skips the Tuesday since it is now at index 0.

like image 32
digidigo Avatar answered Nov 21 '25 15:11

digidigo