改进“每个”陈述

时间:2011-03-11 05:23:15

标签: ruby-on-rails ruby ruby-on-rails-3 each

我正在使用Ruby on Rails 3,我想改进以下代码,以更好的方式来做同样的事情。

query = {}
params.each { |k,v| query[k.singularize] = v }

我该怎么做?

5 个答案:

答案 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!}

但你不能那样做,因为

  1. singularize!未定义,
  2. 当你尝试这样做时:
  3. 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会慢一些吗?