2

I initialized a hash as in this question and ran some benchmarks.

Benchmark.measure { a = h.keys }
#=>  0.010000   0.000000   0.010000 (  0.019832)
Benchmark.measure { a.each { |k| } }
#=>  0.060000   0.000000   0.060000 (  0.057262)
Benchmark.measure { h.each { |k, v| } }
#=>  0.320000   0.000000   0.320000 (  0.319768)
Benchmark.measure { h.each_key { |k| } }
#=>  0.310000   0.000000   0.310000 (  0.312656)
Benchmark.measure { h.each_pair { |k, v| } }
#=>  0.330000   0.000000   0.330000 (  0.331452)

I have thought that turning the hash into an array of keys would be slower, but it's not, and each_key has similar performance to each. Why is this? What is the best approach?

Community
  • 1
  • 1
V_H
  • 1,793
  • 3
  • 34
  • 59

1 Answers1

0

Looking at some code on Github I can tell you 2 words: It depends. If it's not obvious that your variable name is a hash, then using .each_pair will make it obvious (since a hash is a collection of key-value PAIRs). If your variable name mentions 'hash', then this makes sense: hash.each |key, value|. It doesn't make sense to do something like hash.each_pair do |k| where you pass 1 block argument to `each_pair, it makes the code look confusing.

From analyzing several pages on Github, I'm tempted to conclude that the "best approach" is when using .each, you should name your block variables |key, value| to make it very obvious you're iterating over a hash (the block arguments will give you a clue it's a hash). When using .each_pair, you can be a bit more ambiguous about naming the block arguments like |my_key_1, my_key_2| since .each_pair is saying you're iterating over a hash. It's all about looking at your code 1 week (or month) later and being able to INSTANTLY tell what's going on. Unlike with Python, Ruby doesn't have "one right way" to do something.

daremkd
  • 8,244
  • 6
  • 40
  • 66