2010-02-09 35 views
1

我有散列的數組替換的話,每個哈希有兩個密鑰:「從」和「到」從字典

@dictionary = [{:to=>"lazy", :from=>"quick"}, {:to=>"flies", :from=>"jumps"}, {:from => "over the", :to => "under the"}] 

我有一些長串

@text = "quick brown fox jumps over the lazy dog" 

我怎樣才能將所有出現的「從」句子替換爲詞典的「到」句子?

輸出應該是:

lazy brown fox flies under the lazy dog

什麼是最有效的方法是什麼?

+1

將字典存儲爲散列是否更有意義? '@dictionary = {'lazy'=>'quick','flies'=>'jumps','''在'}'下的'=>' – kejadlen 2010-02-09 18:32:20

回答

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

或者,如果你更喜歡它在一行:

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

這是完全相同的代碼,只需使用{ }代替do end對於塊(這往往成爲一般的Ruby練習)。

+0

「all occurences」,所以不是'sub'應該是'gsub'。 – NVI 2010-02-09 15:42:04

+0

好點,謝謝NV。現在更新。 – mlambie 2010-02-09 15:43:09

0
@dictionary.inject(@text) {|text, d| 
    text.gsub d[:from], d[:to] 
} 
+0

@dictionary = [{:to =>「crazy bob」, :from =>「lazy」},{:to =>「mad ben」,:from =>「crazy bob」}] 「快速棕色狐狸跳過瘋狗」 正如你所見,相同的文本被替換兩次,是否有人知道一個運行的解決方案(不覆蓋以前的替換)? 好工作@NV,謝謝 – astropanic 2010-02-09 15:38:46

+0

你期望輸出什麼? 「快速的棕色狐狸跳過瘋狗」還是不? – NVI 2010-02-09 15:49:47

+0

我的意思是在我之前的評論中,從懶惰到瘋狂鮑勃的第一個替換後來被瘋狂的鮑勃替換爲瘋狂的本。它不應該替代現有的替代品。 – astropanic 2010-02-09 17:51:02

0
@enhaced_dictionary = @dictionary.inject({}) {|res, e| res[e[:from]] = e[:to] } 
@compiled = @text.split(/\s/).map do |e| 
    @enhaced_dictionary[e] ? @enhaced_dictionary[e] : e 
end.join(' ') 
+0

'IndexError:string not matched' – 2010-02-09 16:06:09

1

如果它只是沒有{"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]} 
    [email protected](/ /).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"}] 
    @[email protected]*15 

    benchmark.report do 
    h=Hash.new 
    @dictionary.each {|ft| h[ft[:from]]=ft[:to]} 
    [email protected](/ /).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解決方案最終速度一樣快,但實際上只有105個替換對比三個速度慢了10%。 gsub!慢了五倍。

+0

我不認爲'split'和'join'是個好主意。如果'@text =「懶惰的狐狸\ n飛過\」懶惰的狗''? – NVI 2010-02-09 16:02:56