Skip to content

Commit 137625c

Browse files
committed
Added: other methods of slicing Hash values, when keys may not exist.
1 parent a4723f4 commit 137625c

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

README.md

+47
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,53 @@ Comparison:
986986
Hash#slice#values: 4817081.6 i/s - 1.57x slower
987987
```
988988

989+
##### `Hash#values_at` vs `Array#map { Hash#[] }`
990+
[code](code/hash/values_at-vs-map.rb)
991+
992+
To select hash values by keys, when some of the keys may not exist in the hash,
993+
and you care about the default values.
994+
995+
```
996+
$ ruby -v code/hash/values_at-vs-map.rb
997+
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin18]
998+
Warming up --------------------------------------
999+
Hash#values_at 245.809k i/100ms
1000+
Array#map { Hash#[] } 185.153k i/100ms
1001+
Calculating -------------------------------------
1002+
Hash#values_at 5.284M (± 3.3%) i/s - 26.547M in 5.030606s
1003+
Array#map { Hash#[] } 3.104M (± 2.7%) i/s - 15.553M in 5.014067s
1004+
1005+
Comparison:
1006+
Hash#values_at : 5283787.1 i/s
1007+
Array#map { Hash#[] }: 3104255.1 i/s - 1.70x slower
1008+
```
1009+
1010+
##### `Hash#slice#values` vs `Hash#values_at#compact` vs `Array#map { Hash#[] }#compact`
1011+
[code](code/hash/values_at-vs-map.rb)
1012+
1013+
To select hash values by keys, when some of the keys may not exist in the hash,
1014+
and you care only about the intersection (i.e. ignore the default values).
1015+
1016+
NOTE: `#compact`-based methods only work when the default value of `Hash` is
1017+
`nil`.
1018+
1019+
```
1020+
$ ruby -v code/hash/values_at-compact-vs-slice-values-vs-map-compact.rb
1021+
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin18]
1022+
Warming up --------------------------------------
1023+
Hash#slice#values 227.519k i/100ms
1024+
Hash#values_at#compact 211.820k i/100ms
1025+
Array#map#compact 159.760k i/100ms
1026+
Calculating -------------------------------------
1027+
Hash#slice#values 4.420M (± 1.5%) i/s - 22.297M in 5.046173s
1028+
Hash#values_at#compact 3.926M (± 1.6%) i/s - 19.699M in 5.019481s
1029+
Array#map#compact 2.508M (± 2.2%) i/s - 12.621M in 5.034508s
1030+
1031+
Comparison:
1032+
Hash#slice#values : 4419599.9 i/s
1033+
Hash#values_at#compact: 3925677.1 i/s - 1.13x slower
1034+
Array#map#compact : 2508230.2 i/s - 1.76x slower
1035+
```
9891036

9901037
### Proc & Block
9911038

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
require 'benchmark/ips'
2+
3+
HASH = {
4+
a: 'foo',
5+
b: 'bar',
6+
c: 'baz',
7+
d: 'qux'
8+
}.freeze
9+
10+
# Some of the keys may not exist in the hash; we don't care about the default values.
11+
KEYS = %i[a c e f].freeze
12+
13+
# NOTE: This is the only correct method, if the default value of Hash may be not nil.
14+
def fast
15+
HASH.slice(*KEYS).values
16+
end
17+
18+
def slow
19+
HASH.values_at(*KEYS).compact
20+
end
21+
22+
def slowest
23+
KEYS.map { |key| HASH[key] }.compact
24+
end
25+
26+
Benchmark.ips do |x|
27+
x.report('Hash#slice#values ') { fast }
28+
x.report('Hash#values_at#compact') { slow }
29+
x.report('Array#map#compact ') { slowest }
30+
x.compare!
31+
end

code/hash/values_at-vs-map.rb

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'benchmark/ips'
2+
3+
HASH = {
4+
a: 'foo',
5+
b: 'bar',
6+
c: 'baz',
7+
d: 'qux'
8+
}.freeze
9+
10+
# Some of the keys may not exist in the hash; we want to keep the default values.
11+
KEYS = %i[a c e f].freeze
12+
13+
def fast
14+
HASH.values_at(*KEYS)
15+
end
16+
17+
def slow
18+
KEYS.map { |key| HASH[key] }
19+
end
20+
21+
Benchmark.ips do |x|
22+
x.report('Hash#values_at ') { fast }
23+
x.report('Array#map { Hash#[] }') { slow }
24+
x.compare!
25+
end

0 commit comments

Comments
 (0)