簡體   English   中英

從紅寶石哈希中的匹配鍵檢索值的更好方法

[英]Better way to retrieve values from matching keys in a ruby hash

我正在嘗試為SOAP API創建更快的解析器,該解析器會將xml轉換為哈希,然后將鍵與基於YML結構的內存加載模式進行匹配。 我使用Nori將xml解析為哈希:

hash1 = { :key1 => { :@attr1=> "value1", :key2 => { :@attribute2 => "value2" }}}

(舊的ruby語法可以使鍵的屬性保持清晰)

同時,我有一個常量被加載到內存中並存儲執行操作所需的相關鍵:

hash2 = {:key1 => { :key2 => { :@attribute2 => nil }}}

(舊的ruby語法可以使鍵的屬性保持清晰)

我需要以最有效的方式將第一個哈希與第二個哈希進行匹配。 根據我的理解,有幾種方法可以做到:

同時迭代兩個哈希鍵,但將第二個哈希鍵用作起點:

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

(多行語法,¿clear?)

我想到了一些問題:

  • 有沒有更有效的方法可以執行此操作而不必遍歷我的所有鍵?
  • 這比直接訪問密鑰更有效嗎?
  • 是否有更好的方法使用Visitor模式中的hash2將XML解析為哈希?

沒有迭代的解決方案可以是遞歸選擇:

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"}}}

通常,由於復雜的選擇算法, select應該比each select都要好。 實際上,差異僅約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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM