A Ruby reject! that returns the rejected items

I often need to do a reject! and return the rejected items instead of the modified collection. This saves having to do a select beforehand.

An example of how accomplish this:

options = { :a => 1, :b => 2, :c => 3 }
rejects = Hash[*options.select { |k, v| k == :b && options.delete(k) }.flatten]
 
assert_equal { :a => 1, :c => 3 }, options
assert_equal { :b => 2 }, rejects

This could be written as a method of the Hash class and an alternative for Array.

For Hash, the code would look something like:

class Hash
  def extract!
    Hash[*self.select { |k, v| yield(k, v) && self.delete(k) }.flatten]
  end
end
 
options = { :a => 1, :b => 2, :c => 3 }
rejects = options.extract! { |k, v| k == :b }
 
assert_equal { :a => 1, :c => 3 }, options
assert_equal { :b => 2 }, rejects

If I am missing something obvious in Ruby that accomplishes the same, please leave a comment.

Tags: , ,

One comment

  1. The array variation could look something like this

    class Array

    def extract!
    [].tap{|rejected| delete_if { |v| yield(v) && rejected << v }}
    end

    end

Leave a comment