Если бы это были только слова без {"over the"=>"under the"}
, то я думаю, что нечто подобное будет быстрее, чем сканирование строки снова и снова, как это делают большинство решений здесь.
Сначала я конвертирую массив в чистый хэш
h=Hash.new
@dictionary.each {|ft| h[ft[:from]]=ft[:to]}
=> {"quick"=>"lazy", "over the"=>"under the", "jumps"=>"flies"}
затем я сканирую строковое слово за словом
@text.split(/ /).each{|w| h[w] || w}.join(" ")
=> "lazy brown fox flies over the lazy dog"
Также он не страдает от проблемы множественной замены.
h["brown"]="quick"
=> {"brown"=>"quick", "quick"=>"lazy", "over the"=>"under the", "jumps"=>"flies"}
@text.split(/ /).each{|w| h[w] || w}.join(" ")
=> "lazy quick fox flies over the lazy dog"
Я провел несколько тестов и мне пришлось добавить намного больше пар замены, чем я думал, прежде чем решение, приведенное выше, стало быстрее, чем gsub!
.
require 'benchmark'
@dictionary = [{:to=>"lazy", :from=>"quick"}, {:to=>"flies", :from=>"jumps"}, {:from => "over the", :to => "under the"}]
@text = "quick brown fox jumps over the lazy dog" * 10000
Benchmark.bm do |benchmark|
benchmark.report do
h=Hash.new
@dictionary.each {|ft| h[ft[:from]]=ft[:to]}
result=@text.split(/ /).each{|w| h[w] || w}.join(' ')
end
benchmark.report do
@dictionary.each { |pair| @text.gsub!(/#{pair[:from]}/, pair[:to]) }
end
@dictionary+=[{:to=>"black", :from=>"brown"}, {:to=>"ox", :from=>"fox"}, {:to=>"hazy", :from=>"lazy"}, {:to=>"frog", :from=>"dog"}]
@dictionary=@dictionary*15
benchmark.report do
h=Hash.new
@dictionary.each {|ft| h[ft[:from]]=ft[:to]}
result=@text.split(/ /).each{|w| h[w] || w}.join(' ')
end
benchmark.report do
@dictionary.each { |pair| @text.gsub!(/#{pair[:from]}/, pair[:to]) }
end
end
Результаты:
user system total real
0.890000 0.060000 0.950000 ( 0.962106)
0.200000 0.020000 0.220000 ( 0.217235)
0.980000 0.060000 1.040000 ( 1.042783)
0.980000 0.030000 1.010000 ( 1.011380)
Решение gsub!
было в 4,5 раза быстрее всего с тремя замененными парами.
При 105 заменяющих парах решение split
, наконец, является таким же быстрым, на самом деле оно только на 10% медленнее с 105 заменяющими парами, чем для трех. gsub!
стал в пять раз медленнее.