Skip to content

Commit 2696656

Browse files
committed
Added: other methods of slicing Hash values, when keys may not exist.
1 parent 47e9ce1 commit 2696656

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
@@ -1061,6 +1061,53 @@ Comparison:
10611061
Hash#slice#values: 4817081.6 i/s - 1.57x slower
10621062
```
10631063

1064+
##### `Hash#values_at` vs `Array#map { Hash#[] }`
1065+
[code](code/hash/values_at-vs-map.rb)
1066+
1067+
To select hash values by keys, when some of the keys may not exist in the hash,
1068+
and you care about the default values.
1069+
1070+
```
1071+
$ ruby -v code/hash/values_at-vs-map.rb
1072+
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin18]
1073+
Warming up --------------------------------------
1074+
Hash#values_at 245.809k i/100ms
1075+
Array#map { Hash#[] } 185.153k i/100ms
1076+
Calculating -------------------------------------
1077+
Hash#values_at 5.284M (± 3.3%) i/s - 26.547M in 5.030606s
1078+
Array#map { Hash#[] } 3.104M (± 2.7%) i/s - 15.553M in 5.014067s
1079+
1080+
Comparison:
1081+
Hash#values_at : 5283787.1 i/s
1082+
Array#map { Hash#[] }: 3104255.1 i/s - 1.70x slower
1083+
```
1084+
1085+
##### `Hash#slice#values` vs `Hash#values_at#compact` vs `Array#map { Hash#[] }#compact`
1086+
[code](code/hash/values_at-vs-map.rb)
1087+
1088+
To select hash values by keys, when some of the keys may not exist in the hash,
1089+
and you care only about the intersection (i.e. ignore the default values).
1090+
1091+
NOTE: `#compact`-based methods only work when the default value of `Hash` is
1092+
`nil`.
1093+
1094+
```
1095+
$ ruby -v code/hash/values_at-compact-vs-slice-values-vs-map-compact.rb
1096+
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin18]
1097+
Warming up --------------------------------------
1098+
Hash#slice#values 227.519k i/100ms
1099+
Hash#values_at#compact 211.820k i/100ms
1100+
Array#map#compact 159.760k i/100ms
1101+
Calculating -------------------------------------
1102+
Hash#slice#values 4.420M (± 1.5%) i/s - 22.297M in 5.046173s
1103+
Hash#values_at#compact 3.926M (± 1.6%) i/s - 19.699M in 5.019481s
1104+
Array#map#compact 2.508M (± 2.2%) i/s - 12.621M in 5.034508s
1105+
1106+
Comparison:
1107+
Hash#slice#values : 4419599.9 i/s
1108+
Hash#values_at#compact: 3925677.1 i/s - 1.13x slower
1109+
Array#map#compact : 2508230.2 i/s - 1.76x slower
1110+
```
10641111

10651112
### Proc & Block
10661113

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)