diff --git a/README.md b/README.md index b0a2e83..d7bcbe1 100644 --- a/README.md +++ b/README.md @@ -1038,6 +1038,26 @@ Array#each_w/_object: 1352851.8 i/s - 1.88x slower Hash#select-include : 760944.2 i/s - 3.34x slower ``` +##### `Hash#values_at` vs `Array#map { Hash#[] }` +[code](code/hash/values_at-vs-map.rb) + +To select hash values by keys, when some of the keys may not exist in the hash, +and you care about the default values. + +``` +$ ruby -v code/hash/values_at-vs-map.rb +ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22] +Warming up -------------------------------------- +Hash#values_at 503.783k i/100ms +Array#map { Hash#[] } 279.576k i/100ms +Calculating ------------------------------------- +Hash#values_at 4.901M (± 4.1%) i/s - 24.685M in 5.046090s +Array#map { Hash#[] } 2.801M (± 3.1%) i/s - 14.258M in 5.095692s + +Comparison: +Hash#values_at : 4900567.9 i/s +Array#map { Hash#[] }: 2800981.4 i/s - 1.75x slower +``` ### Proc & Block diff --git a/code/hash/values_at-vs-map.rb b/code/hash/values_at-vs-map.rb new file mode 100644 index 0000000..0e860ac --- /dev/null +++ b/code/hash/values_at-vs-map.rb @@ -0,0 +1,25 @@ +require 'benchmark/ips' + +HASH = { + a: 'foo', + b: 'bar', + c: 'baz', + d: 'qux' +}.freeze + +# Some of the keys may not exist in the hash; we want to keep the default values. +KEYS = %i[a c e f].freeze + +def fast + HASH.values_at(*KEYS) +end + +def slow + KEYS.map { |key| HASH[key] } +end + +Benchmark.ips do |x| + x.report('Hash#values_at ') { fast } + x.report('Array#map { Hash#[] }') { slow } + x.compare! +end