From: shevegen@... Date: 2019-05-06T06:01:09+00:00 Subject: [ruby-core:92569] [Ruby trunk Feature#15831] Add `Array#extract!`, `Hash#extract!`, and `ENV::extract!` 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: