从给定值获取所有哈希键的最有效方法是什么.
my_hash = {"a"=>"aa", "b"=>"bb", "c"=>"bb"}
Run Code Online (Sandbox Code Playgroud)
我想将散列"bb"作为输入值,并将它们的所有键(b,c)作为数组返回
只返回一个键:
my_hash.index("bb")
# returns only b
Run Code Online (Sandbox Code Playgroud)
这有效,但似乎效率低下:
my_hash.select{|k,v| v == 'bb' }.map{|i| i[0] }
# returns b and c
Run Code Online (Sandbox Code Playgroud)
我已经阅读了所有的文档.我觉得有一些明显的东西我不知道了.
谢谢!
更新:
我最终切换了哈希创建的键和值,并使用数组来表示值.这是一种更有效的解决方案.如果必须,请参阅下面的最佳方法来进行价值观察.
新结构:
my_hash = {"aa"=>["a"],"bb"=>["b","c"]}
Run Code Online (Sandbox Code Playgroud)
Phr*_*ogz 30
稍快一点:
my_hash.map{ |k,v| v=='bb' ? k : nil }.compact
Run Code Online (Sandbox Code Playgroud)
仅对小哈希和单个查询较慢.如果需要为多个值请求反向映射,则速度更快.如果这对您的应用程序很重要,我建议您保留一张反向地图.
rev = Hash.new{ |h,k| h[k]=[] }
my_hash.each{ |k,v| rev[v] << k }
rev['bb']
Run Code Online (Sandbox Code Playgroud)
基准测试:
require 'benchmark'
N = 1_000_000
my_hash = {"a"=>"aa", "b"=>"bb", "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)
Run Code Online (Sandbox Code Playgroud)