I'm trying to create a faster parser for a SOAP API that will turn the xml into a hash, and the match the keys with a memory loaded schema based on a YML structure. I used Nori to parse the xml into a hash:
hash1 = { :key1 => { :@attr1=> "value1", :key2 => { :@attribute2 => "value2" }}}
(old ruby syntax to keep attributes from keys clear)
Meanwhile I have a constant that is loaded in memory and stores the relevant keys needed for my actions:
hash2 = {:key1 => { :key2 => { :@attribute2 => nil }}}
(old ruby syntax to keep attributes from keys clear)
I need to match the first hash with the second one in the most efficient way. As per my understanding there are ways to do it:
Iterate over the two hash keys at the same time but by using the second one as origin:
def iterate(hash2, hash1)
hash2.each do |k, v|
if v.is_a? Hash
iterate(hash2[k], hash1[k])
else
hash2[k] = hash1[k]
end
end
end
(multiline syntax, ¿clear?)
Some questions come to my mind:
The solution without iteration could be recursive select:
hash1 = { :key1 => { :@attr1=> "value1",
:key2 => { :@attribute2 => "value2" },
:key3 => { :@attribute4 => "value4" } },
:key2 => { :@attribute3 => "value3" }
}
hash2 = { :key1 => { :key2 => { :@attribute2 => nil }},
:key2 => { :@attribute3 => nil }
}
def deep_select h1, h2
h1.select do |k, _|
h2.keys.include? k
end.map do |k, v|
v.is_a?(Hash) ? [k, deep_select(v, h2[k])] : [k, v]
end.to_h
end
puts deep_select hash1, hash2
#⇒ {:key1=>{:key2=>{:@attribute2=>"value2"}}, :key2=>{:@attribute3=>"value3"}}}
In general, select
is supposed to be better than each
because of sophisticated selection algorithm. In reality, the difference is only about 20%.
require 'benchmark'
hash = (1..1_000_000).map { |i| ["key#{i}", i] }.to_h
n = 5
Benchmark.bm do |x|
garbage = 0
x.report { hash.each { |_, v| garbage += v } }
x.report { hash.select { |_, v| (v % 1000).zero? } }
end
# user system total real
# 0.400000 0.000000 0.400000 ( 0.391305)
# 0.320000 0.000000 0.320000 ( 0.321312)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.