Feature #15831
Updated by bogdanvlviv (Bogdan Denkovych) over 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