Ruby 替换字典中的单词

Ruby 替换字典中的单词,ruby,string,Ruby,String,我有一个散列数组,每个散列有两个键:“from”和“to” 我有一些长绳子 @text = "quick brown fox jumps over the lazy dog" 如何将字典中所有出现的“from”句子替换为“to”句子 输出应为: 懒惰的棕色狐狸在懒惰的狗下面飞 最有效的方法是什么 @dictionary.inject(@text) {|text, d| text.gsub d[:from], d[:to] } 或者,如果您喜欢在一行中使用: @dictionary.eac

我有一个散列数组,每个散列有两个键:“from”和“to”

我有一些长绳子

@text = "quick brown fox jumps over the lazy dog"
如何将字典中所有出现的“from”句子替换为“to”句子

输出应为:

懒惰的棕色狐狸在懒惰的狗下面飞

最有效的方法是什么

@dictionary.inject(@text) {|text, d|
  text.gsub d[:from], d[:to]
}
或者,如果您喜欢在一行中使用:

@dictionary.each { |pair| @text.gsub!(/#{pair[:from]}/, pair[:to]) }
这是完全相同的代码,只是对块使用
{}
而不是
do end
(这通常是Ruby的惯例)

或者,如果您喜欢在一行中使用:

@dictionary.each { |pair| @text.gsub!(/#{pair[:from]}/, pair[:to]) }

这是完全相同的代码,只是对块使用
{}
而不是
do end
(这通常是Ruby的惯例)。

如果在“}下的“=>”上只有单词没有
{”
然后我认为这样做比像这里的大多数解决方案那样反复扫描字符串要快

首先,我将数组转换为纯散列

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) 用户系统总真实值 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
解决方案最终也同样快,实际上,105个替换对比3个替换对慢10%。
gsub慢了五倍。

如果只有单词没有“}
下的“=>”上的
{”,那么我认为这样做会比像这里的大多数解决方案那样一遍又一遍地扫描字符串快

首先,我将数组转换为纯散列

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) 用户系统总真实值 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
解决方案最终也同样快,实际上,105个替换对比3个替换对慢10%。
gsub变慢了五倍。

@dictionary=[{:to=>“疯狂的鲍勃”,“from=>“懒惰”},{:to=>“疯狂的本”,“from=>“疯狂的鲍勃”}]“快速的棕色狐狸跳过了疯狂的本狗”正如你所看到的,相同的文本被替换了两次,有人知道一个一次运行的解决方案吗(不覆盖以前的替换)?干得好@NV,谢谢你期望什么输出?“快跑的棕色狐狸跳过了疯狗”还是没有?我的意思是在我之前的评论中,第一个从懒惰到疯狂的鲍勃的替换后来被从疯狂的鲍勃到疯狂的本所取代。它不应该替换现有的替换项。@dictionary=[{:to=>“疯狂的鲍勃”,“from=>“懒惰”},{:to=>“疯狂的本”,“疯狂的鲍勃”}]“QuickBrown fox跳过了疯狂的本狗”正如你所看到的,同一个文本被替换了两次,有人知道一个单次运行的解决方案(不覆盖以前的替换项)吗?干得好@NV,谢谢你期望什么输出?“快跑的棕色狐狸跳过了疯狗”还是没有?我的意思是在我之前的评论中,第一个从懒惰到疯狂的鲍勃的替换后来被从疯狂的鲍勃到疯狂的本所取代。它不应该取代现有的替换。“所有发生”,所以应该是
sub
而不是
gsub
“所有发生”,所以应该是
sub
而不是
gsub
。我不认为
split
join
是个好主意。如果
@text=“lazy quick fox\n飞越懒狗”
?我认为
拆分
加入
不是一个好主意。如果
@text=“lazy quick fox\n飞越\t lazy dog”
索引器:字符串不匹配
索引器:字符串不匹配
将字典存储为散列会更有意义吗
@dictionary={'lazy'=>'quick','flies'=>'jumps','over the'=>'下的'}
将字典存储为散列不是更有意义吗
@dictionary={'lazy'=>'quick','flies'=>'jumps','over the'=>'在'}下