Улучшение каждого утверждения - PullRequest
1 голос
/ 11 марта 2011

Я использую Ruby on Rails 3, и я хотел бы улучшить следующий код для лучшего способа сделать то же самое.

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

Как я могу это сделать?

Ответы [ 5 ]

1 голос
/ 11 марта 2011

Если вы действительно нашли это

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

занимал слишком много времени, singularize занимало бы большую часть вашего времени.

Если бы большинство слов были одинаковыми, я бы подумал: "Записать".

На самом деле, если бы у вас было десять тысяч параметров, я бы рассмотрел обзор кода!

1 голос
/ 11 марта 2011

Как писал nzifnab, мой другой код кажется медленным. Следующий может быть немного быстрее, чем оригинал.

query = params.each_with_object({}){|(k, v), h| h[k.singularize] = v}
1 голос
/ 11 марта 2011
query = Hash[params.map{|k, v| [k.singularize, v]}]
0 голосов
/ 11 марта 2011

Я попробовал следующее в 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

Так что использование Hash медленнее, чем 1.8?

0 голосов
/ 11 марта 2011

Ну, у меня была идея (та же идея, что и у 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 должен циклически проходить через каждый отдельный элемент, чтобы он не отличался.

EDIT:

Я пошел с предложением комментария сделать один действительно большой хэш вместо крошечного 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: Кредит идет в пилу для этого третьего метода:

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. при попытке сделать это:
params.each{|arr| arr[0].gsub!('s', '')}

Вы получаете ошибку:

TypeError: can't modify frozen string

Я бы просто придерживался оригинальной версии: p

...