Project

General

Profile

Feature #15831

Updated by bogdanvlviv (Bogdan Denkovych) almost 5 years ago

## Add `Array#extract` `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 numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9] 
 numbers # => [0, 2, 4, 6, 8] 
 ``` 

 This method was added to Active Support as `extract!` 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` `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) h.extract!(:a) # => {:a=>100} 
 h # => {:b=>200, :c=>300} 
 h.extract(:b, h.extract!(:b, :c, :d) # => {:b=>200, :c=>300} 
 h # => {} 
 ``` 

 This method was added to Active Support as `extract!` 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` `ENV::extract!` 

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

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

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

Back