ハッシュを文字列でもシンボルでも使えるようにしたかった

ハッシュを使う時、h[:key]だったりh["key"]といった、文字列とシンボルでキーを設定できます。
しかし、自前で作ったのならまだしもライブラリから渡されたハッシュがどちらで指定しているのかわかりにくくも感じます。
どうせなら「どちらでもつかえたらいいのにな。」という記事です。


参考

やり方

最初にですが、参考にした記事のまんまです。

適当なディレクトリで、以下の通り実行します。

1
2
3
4
5
6
bundle init

# Gemfileに以下を追記
# gem 'activesupport'

bundle install --path=vendor/bundle

テスト用のファイルを作成します。

test1.rbを以下の通り作成します。

test1.rb
1
2
3
4
5
6
7
8
require 'active_support'
require 'active_support/core_ext'

h = {"a":123,b: {c:345,d:"123","e": 987 }}.with_indifferent_access

puts h[:a]
puts h["b"]
puts h["b"][:e]

作成できたら、bundle exec ruby test1.rbで起動します。
結果は以下の通りです。

1
2
3
123
{"c"=>345, "d"=>"123", "e"=>987}
987

文字列をキーにしたハッシュをシンボルで呼び出し、シンボルをキーにしたハッシュを文字列で呼び出すことができました。
また、入れ子のハッシュでも同様のことが可能でした。
active_supportの用意してくれた.with_indifferent_accessに感謝です。

気になったので調査

.with_indifferent_accessを使うと文字列とシンボルのキーを相互に読み替えできることはわかりましたが、
変換の負荷ってどうなんだろう?と気になりました。

以下のようにして確認しました。

1
2
3
4
# Gemfileに以下を追記
# gem 'benchmark'

bundle install --path=vendor/bundle

benchmarkをインストールできたら、test2.rbを作成します。

test2.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
require 'active_support'
require 'active_support/core_ext'
require 'benchmark'

sth = {"a":123,"b": "abc"}
sih = { a: 123, b: "abc" }
sth_ind = sth.with_indifferent_access
sih_ind = sih.with_indifferent_access


count=0
buf=0

result = Benchmark.realtime do
while count>100000000
buf=sth["a"]
buf=sth["b"]
end
count+=1
end

puts "処理概要 #{result}s"
count=0

result = Benchmark.realtime do
while count>100000000
buf=sih[:a]
buf=sih[:b]
end
count+=1
end

puts "処理概要 #{result}s"
count=0

result = Benchmark.realtime do
while count>100000000
buf=sth_ind[:a]
buf=sth_ind[:b]
end
count+=1
end

puts "処理概要 #{result}s"
count=0

result = Benchmark.realtime do
while count>100000000
buf=sih_ind["a"]
buf=sih_ind["b"]
end
count+=1
end

puts "処理概要 #{result}s"

作成できたら、bundle exec ruby test2.rbで起動します。
結果は以下の通りです。

1
2
3
4
処理概要 1.100008375942707e-06s
処理概要 8.00006091594696e-07s
処理概要 9.00006853044033e-07s
処理概要 1.0999501682817936e-06s

100000000 回取得を繰り返しましたが、ほとんど差がありませんでした。
これなら負荷は気にせず使っても問題なさそうです。

ではでは。