The Paper Pilot The Paper Pilot - 1 year ago 59
Ruby Question

Deleting elements of an array based on block with loop

I have an array that I want to remove certain elements from based on a set of rules. I've written the code below:

puts "before: #{people.inspect()}"
puts people.size
people.delete_if do |person|
rules.each do |rule|
if rule.check_source(self) && !rule.check_rule(person)
puts "deleted person #{}"
puts "sanity check"
puts "after: #{people.inspect()}"

But that code does not work. The array printed before is the same as the array printed after, and "sanity check" is printed, even though I think it shouldn't. I suspect the issue might be because of the loop inside the delete_if block, but I don't know how to fix that.

Here's the console output after an array with 2 people with IDs 2 and 3, where 2 should be deleted and 3 kept:

before: [#<Person id: 2>, #<Person id: 3>]
deleted person 2
sanity check
after: [#<Person id: 2>, #<Person id: 3>]

Answer Source

Your problem is that the block you're handing to delete_if always evaluates to false. Your code structure is like this:

people.delete_if do |person|
  # Stuff that `delete_if` doesn't care about ...

The value of the each block doesn't matter since each doesn't care what it returns and delete_if would never see that anyway. The blocks for delete_if and each are independent.

You could replace the whole delete_if block with a simpler any? call:

people.delete_if do |person|
  rules.any? { |rule| rule.check_source(self) && !rule.check_rule(person) }

and get the result you're looking for.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download