Issue #15831 has been updated by shevegen (Robert A. Heiler).


What is the difference towards e. g. hash.delete()?

People may ask about this difference. The '!'
too since you can use e. g. Hash #delete as-is.

Also without '!', I am not sure if extract is a good
name per se, but these are just random comments mostly,
you only have to convince matz, not me. :)

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

* 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>