Adrian
Adrian

Reputation: 15171

How can I use Array#delete while iterating over the array?

I have an array that I want to iterate over and delete some of the elements. This doesn't work:

a = [1, 2, 3, 4, 5]
a.each do |x|
  next if x < 3
  a.delete x
  # do something with x
end
a #=> [1, 2, 4]

I want a to be [1, 2]. How can I get around this?

Upvotes: 78

Views: 52482

Answers (4)

Chubas
Chubas

Reputation: 18043

a.delete_if { |x| x >= 3 }

See method documentation here

Update:

You can handle x in the block:

a.delete_if do |element|
  if element >= 3
    do_something_with(element)
    true # Make sure the if statement returns true, so it gets marked for deletion
  end
end

Upvotes: 130

AlexChaffee
AlexChaffee

Reputation: 8252

Another way to do it is using reject!, which is arguably clearer since it has a ! which means "this will change the array". The only difference is that reject! will return nil if no changes were made.

a.delete_if {|x| x >= 3 }

or

a.reject! {|x| x >= 3 }

will both work fine.

Upvotes: 3

Joc
Joc

Reputation: 1059

You don't have to delete from the array, you can filter it so:

a = [1, 2, 3, 4, 5]

b = a.select {|x| x < 3}

puts b.inspect # => [1,2]

b.each {|i| puts i} # do something to each here

Upvotes: 7

Jesse Jashinsky
Jesse Jashinsky

Reputation: 10663

I asked this question not long ago.

Deleting While Iterating in Ruby?

It's not working because Ruby exits the .each loop when attempting to delete something. If you simply want to delete things from the array, delete_if will work, but if you want more control, the solution I have in that thread works, though it's kind of ugly.

Upvotes: 5

Related Questions