since each iterates with the indices, and you delete the element in the inner loop every other element of the next iteration. if you increase the number of elements and include the current iteration index in the loop, you will see a large picture.
arr = [1,2,3,4,5,6,7,8,9] arr.each_with_index do |x,ix| puts "loop1: #{arr.inspect}, x: #{x}, ix: #{ix}" arr.each_with_index do |y, iy| puts "loop2: #{arr.inspect}, y: #{y}, iy: #{iy}" puts "#{arr.delete(y)}" end end
result
loop1: [1, 2, 3, 4, 5, 6, 7, 8, 9], x: 1, ix: 0 loop2: [1, 2, 3, 4, 5, 6, 7, 8, 9], y: 1, iy: 0 1 loop2: [2, 3, 4, 5, 6, 7, 8, 9], y: 3, iy: 1 3 loop2: [2, 4, 5, 6, 7, 8, 9], y: 5, iy: 2 5 loop2: [2, 4, 6, 7, 8, 9], y: 7, iy: 3 7 loop2: [2, 4, 6, 8, 9], y: 9, iy: 4 9 loop1: [2, 4, 6, 8], x: 4, ix: 1 loop2: [2, 4, 6, 8], y: 2, iy: 0 2 loop2: [4, 6, 8], y: 6, iy: 1 6 => [4, 8]
since you delete during the loop, and after each iteration, the index increases, but the array is one of the elements, so it removes the next (and all) corresponding element (s), available, and at the end the loop compares and stops the loop when index >= length