我正在使用Ruby on Rails 3,我想改进以下代码,以更好的方式来做同样的事情。
query = {}
params.each { |k,v| query[k.singularize] = v }
我该怎么做?
答案 0 :(得分:1)
query = Hash[params.map{|k, v| [k.singularize, v]}]
答案 1 :(得分:1)
正如nzifnab所写,我的其他代码似乎很慢。以下内容可能比原始发布的内容略快。
query = params.each_with_object({}){|(k, v), h| h[k.singularize] = v}
答案 2 :(得分:1)
如果你真的找到了那个
params.each { |k,v| query[k.singularize] = v }
花费的时间过长,singularize
占用了大部分时间。
如果大多数单词都相同,我会考虑记忆。
实际上,如果你有一万个参数,我会考虑进行代码审查!
答案 3 :(得分:0)
我有一个想法(与sawa相同的想法),并决定我想知道它是否有所改善。以下是基准测试结果:
params = {'puppies' => 'cute',
'dinosaurs' => 'angry',
'kittens' => 'kill them all',
'wat' => 4}
Benchmark.bm do |x|
x.report(".each"){10000.times{query = {}; params.each{ |k,v| query[k.singularize] = v }}}
x.report("Hash"){10000.times{query = Hash[params.map{|k, v| [k.singularize, v]}]}}
end
结果:
user system total real
.each 3.850000 0.390000 4.240000 ( 4.260567)
Hash 3.910000 0.400000 4.310000 ( 4.402304)
差别很小,虽然Hash与改进相反,但遗憾的是 - 如果表现是你的担忧。
我仍然倾向于使用Hash[]
格式,因为我喜欢.map
的工作方式......但.map
也必须遍历每个项目,所以它没有什么不同。
编辑:
我使用评论建议做了一个非常大的哈希而不是微小哈希10,000次。结果如下:
myhash = {}
20000.times do |i|
myhash[i.to_s * 2 + 's'] = i
end
Benchmark.bm do |x|
x.report(".each"){query = {}; myhash.each{|k,v| query[k.singularize] = v}}
x.report("Hash"){query = Hash[myhash.map{|k,v| [k.singularize, v]}]}
end
结果:
user system total real
.each 1.980000 0.110000 2.090000 ( 2.100811)
Hash 2.040000 0.140000 2.180000 ( 2.176588)
编辑2:对于第三种方法,学分归于sawa:
Benchmark.bm do |x|
x.report(".each"){query = {}; myhash.each{|k,v| query[k.singularize] = v}}
x.report("Hash"){query = Hash[myhash.map{|k,v| [k.singularize, v]}]}
x.report("with_object"){query = myhash.each_with_object({}){|(k, v), h| h[k.singularize] = v}}
end
user system total real
.each 2.050000 0.110000 2.160000 ( 2.174315)
Hash 2.070000 0.110000 2.180000 ( 2.187600)
with_object 2.100000 0.110000 2.210000 ( 2.207763)
如果您(或某人)可以找到一种方法来就地修改每个值,我怀疑这是最快的方法:
params.each{|arr| arr[0].singularize!}
但你不能那样做,因为
singularize!
未定义,params.each{|arr| arr[0].gsub!('s', '')}
您收到错误消息:
TypeError: can't modify frozen string
我会坚持使用原始版本:p
答案 4 :(得分:0)
我在Ruby YARV 1.9.1中尝试了以下内容,没有ActiveSupport(因此reverse
而不是singularize
)
require "benchmark"
myhash = {}
2000000.times do |i|
myhash[i.to_s * 2 + 's'] = i
end
Benchmark.bm do |x|
x.report(".each"){query = {}; myhash.each{|k,v| query[k.reverse] = v}}
x.report("Hash"){query = Hash[myhash.map{|k,v| [k.reverse, v]}]}
puts RUBY_VERSION
puts RUBY_ENGINE if defined?(RUBY_ENGINE)
end
给了我
user system total real
.each 6.350000 0.070000 6.420000 ( 6.415588)
Hash 5.710000 0.100000 5.810000 ( 5.795611)
1.9.1
ruby
所以在我的情况下,Hash更快。
考虑到我的基准测试和nzifnab之间的速度差异,我想检查大部分时间没花在singularize
上。
<强>更新强>
1.8.7以下:
user system total real
.each 11.640000 0.380000 12.020000 ( 12.019372)
Hash 15.010000 0.540000 15.550000 ( 15.552186)
1.8.7
所以在1.8以下使用Hash会慢一些吗?