Skip to content

Instantly share code, notes, and snippets.

@mfpiccolo
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mfpiccolo/797cc8849df4b3b4f55f to your computer and use it in GitHub Desktop.
Save mfpiccolo/797cc8849df4b3b4f55f to your computer and use it in GitHub Desktop.
require "json"
require 'benchmark'
require 'bigdecimal/math'
class Hash
def to_struct
k = self.keys
klass = k.map(&:to_s).sort_by {|word| word.downcase}.join.capitalize
begin
Kernel.const_get("Struct::" + klass).new(*self.values_at(*k))
rescue NameError
Struct.new(klass, *(k)).new(*self.values_at(*k))
end
end
end
# You have a hash that you have built in your app
sample_hash = {
foo_key: "foo_val",
bar_key: "bar_val",
baz_key: "baz_val",
foo1_key: "foo_val",
bar1_key: "bar_val",
baz1_key: "baz_val",
foo2_key: "foo_val",
bar2_key: "bar_val",
baz2_key: "baz_val",
foo3_key: "foo_val",
bar3_key: "bar_val",
baz3_key: "baz_val",
foo4_key: "foo_val",
bar4_key: "bar_val",
baz4_key: "baz_val",
foo5_key: "foo_val",
bar5_key: "bar_val",
baz5_key: "baz_val",
foo6_key: "foo_val",
bar6_key: "bar_val",
baz6_key: "baz_val",
foo7_key: "foo_val",
bar7_key: "bar_val",
baz7_key: "baz_val",
}
# Then you have JSON coming from some external api
json_response = "{\"qux_key\":\"qux_val\",\"quux_key\":\"quux_val\",\"corge_key\":\"corge_val\"}"
hash_with_unknown_keys = JSON.parse(json_response)
# Merge these two together
sample_hash.merge!(hash_with_unknown_keys)
iterations = 100_000
Benchmark.bm do |bm|
bm.report "#to_struct" do
iterations.times do
# Would be super nice if I could convert this to a struct with a method
# Somehow a bit faster than the explicit example below and much faster than open struct
sample_struct = sample_hash.to_struct
unless sample_struct.foo_key == "foo_val"
raise "Wrong value"
end
end
end
bm.report "Struct" do
iterations.times do
sample_struct = Struct.new(*sample_hash.keys)
.new(*sample_hash.values)
unless sample_struct.foo_key == "foo_val"
raise "Wrong value"
end
end
end
bm.report "OpenStruct" do
iterations.times do
sample_open_struct = OpenStruct.new(sample_hash)
unless sample_open_struct.foo_key == "foo_val"
raise "Wrong value"
end
end
end
end
# user system total real
# #to_struct 4.030000 0.010000 4.040000 ( 4.072031)
# Struct 6.870000 0.290000 7.160000 ( 7.320459)
# OpenStruct 23.550000 0.210000 23.760000 ( 23.895187)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment