从给定值获取所有散列键的最有效方式是什么?
my_hash = {"a"=>"aa","b"=>"bb","c"=>"bb"}
我想把散列“bb”作为一个输入值,并将它们的所有键(b,c)作为数组返回
只返回一个键:
my_hash.index("bb") # returns only b
这有效但似乎效率不高:
my_hash.select{|k,v| v == 'bb' }.map{|i| i[0] } # returns b and c
我已经阅读了所有的文档.我觉得有一些明显的东西我失踪了.
谢谢!
更新:
我结束了切换哈希创建的键和值,并使用数组的值.这是一个更有效的解决方案.如果需要,请参阅下面的最佳方法来进行价值查询.
新结构:
my_hash = {"aa"=>["a"],"bb"=>["b","c"]}
解决方法
稍微快一点
my_hash.map{ |k,v| v=='bb' ? k : nil }.compact
较小的哈希和单个查询的速度较慢.如果需要为多个值请求反向映射,则更快.如果这对您的应用程序很重要,我建议维护一个反向地图.
rev = Hash.new{ |h,k| h[k]=[] } my_hash.each{ |k,v| rev[v] << k } rev['bb']
基准测试:
require 'benchmark' N = 1_000_000 my_hash = {"a"=>"aa","c"=>"bb"} Benchmark.bmbm do |x| x.report('select/map'){ N.times{ my_hash.select{|k,v|v=='bb'}.map{|i| i[0]} }} x.report('select/map/destructure'){ N.times{ my_hash.select{|k,v|v=='bb'}.map{|k,v| k} }} x.report('map/compact'){ N.times{ my_hash.map{|k,v|v=='bb' ? k : nil}.compact }} x.report('reverse map'){ N.times{ rev = Hash.new{|h,k|h[k]=[]} my_hash.each{ |k,v| rev[v]<<k } rev['bb'] }} x.report('reject'){ N.times{ my_hash.reject{|k,v|v != "bb"}.keys }} end #=> Rehearsal ---------------------------------------------------------- #=> select/map 1.950000 0.000000 1.950000 ( 1.950137) #=> select/map/destructure 1.960000 0.010000 1.970000 ( 1.963740) #=> map/compact 1.200000 0.000000 1.200000 ( 1.197340) #=> reverse map 3.660000 0.000000 3.660000 ( 3.658245) #=> reject 2.110000 0.000000 2.110000 ( 2.115805) #=> ------------------------------------------------ total: 10.890000sec #=> #=> user system total real #=> select/map 1.950000 0.000000 1.950000 ( 1.948784) #=> select/map/destructure 1.970000 0.010000 1.980000 ( 1.966636) #=> map/compact 1.190000 0.000000 1.190000 ( 1.192052) #=> reverse map 3.670000 0.000000 3.670000 ( 3.664798) #=> reject 2.140000 0.000000 2.140000 ( 2.135069)