Issue #15831 has been reported by bogdanvlviv (Bogdan Denkovych).

----------------------------------------
Feature #15831: Add `Array#extract!`, `Hash#extract!`, and `ENV::extract!`
https://bugs.ruby-lang.org/issues/15831

* Author: bogdanvlviv (Bogdan Denkovych)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Add `Array#extract!`

The method removes and returns the elements for which the block returns a true value.
If no block is given, an Enumerator is returned instead.

```ruby
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
numbers # => [0, 2, 4, 6, 8]
```

This method was added to Active Support in https://github.com/rails/rails/pull/33137

In this post, you can find use cases of this method
https://bogdanvlviv.com/posts/ruby/rails/array-extract-to-activesupport-6-0.html

There is a benchmark script:

```ruby
require "benchmark"

class Array
  def activesupport_extract!
    return to_enum(:activesupport_extract!) { size } unless block_given?

    extracted_elements = []

    reject! do |element|
      extracted_elements << element if yield(element)
    end

    extracted_elements
  end
end

arrays_for_partition = Array.new(1000) { (0..10000).to_a }
arrays_for_extract = Array.new(1000) { (0..10000).to_a }
arrays_for_activesupport_extract = Array.new(1000) { (0..10000).to_a }

Benchmark.bmbm do |x|
  x.report("Array#partition")  do
    arrays_for_partition.each do |numbers|
      odd_numbers, numbers = numbers.partition { |number| number.odd? }
      numbers
    end
  end

  x.report("Array#extract!")  do
    arrays_for_extract.each do |numbers|
      odd_numbers = numbers.extract! { |number| number.odd? }
      numbers
    end
  end

  x.report("Array#activesupport_extract!")  do
    arrays_for_activesupport_extract.each do |numbers|
      odd_numbers = numbers.activesupport_extract! { |number| number.odd? }
      numbers
    end
  end
end

and its result:

```bash
Rehearsal ----------------------------------------------------------------
Array#partition                0.657710   0.003571   0.661281 (  0.662462)
Array#extract!                 0.509381   0.002581   0.511962 (  0.513105)
Array#activesupport_extract!   0.811371   0.000000   0.811371 (  0.812456)
------------------------------------------------------- total: 1.984614sec

                                   user     system      total        real
Array#partition                0.623502   0.000000   0.623502 (  0.625004)
Array#extract!                 0.193920   0.000000   0.193920 (  0.194283)
Array#activesupport_extract!   0.308468   0.000000   0.308468 (  0.309037)
```

#################################################################################

Add `Hash#extract!`

The method removes and returns the key/value pairs matching the given keys.

```ruby
h = {a: 100, b: 200, c: 300}
h.extract!(:a) # => {:a=>100}
h # => {:b=>200, :c=>300}
h.extract!(:b, :c, :d) # => {:b=>200, :c=>300}
h # => {}
```

This method was added to Active Support in 2009, see
https://github.com/rails/rails/commit/8dcf91ca113579646e95b0fd7a864dfb6512a53b

There is a benchmark script:

```ruby
require "benchmark"

class Hash
  def activesupport_extract!(*keys)
    keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
  end
end

Benchmark.bmbm do |x|
  x.report("Hash#extract")  do
    10000.times do
      hash_for_extract =  { a: 1, b: 2, c: 3, d: 4 }
      executed = hash_for_extract.extract!(:a, :b, :d, :x, :y)
    end
  end

  x.report("Hash#activesupport_extract!")  do
    10000.times do
      hash_for_activesupport_extract =  { a: 1, b: 2, c: 3, d: 4 }
      executed = hash_for_activesupport_extract.activesupport_extract!(:a, :b, :d, :x, :y)
    end
  end
end
```

and its result:

```bash
Rehearsal ---------------------------------------------------------------
Hash#extract                  0.004724   0.000000   0.004724 (  0.004670)
Hash#activesupport_extract!   0.005686   0.004434   0.010120 (  0.010248)
------------------------------------------------------ total: 0.014844sec

                                  user     system      total        real
Hash#extract                  0.002562   0.000000   0.002562 (  0.002715)
Hash#activesupport_extract!   0.009864   0.000000   0.009864 (  0.009997)
```

#################################################################################

Add `ENV::extract!`

The method removes and returns the key/value pairs matching the given keys.

```ruby
ENV.extract!("TERM","HOME") # => {"TERM"=>"xterm-256color", "HOME"=>"/Users/rhc"}
```

Pull Request: https://github.com/ruby/ruby/pull/2171



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>