2017-02-24 65 views
0

我有以下文字:使用多種模式替換互不

a phrase whith length one, which is "uno" 

使用下面的字典,

1) phrase --- frase 
2) a phrase --- una frase 
3) one --- uno 
4) uno --- one 

我試圖替換文本詞典項目的出現。所需的輸出是:

[a phrase|una frase] whith length [one|uno], which is "[uno|one]" 

我已經做到了這一點:

text = %(a phrase whith length one, which is "uno") 
dictionary.each do |original, translation| 
    text.gsub! original, "[#{original}|#{translation}]" 
end 

這段代碼輸出下面的每個字典中的單詞:

1) a [phrase|frase] whith length one, which is "uno" 
2) a [phrase|frase] whith length one, which is "uno" 
3) a [phrase|frase] whith length [one|uno], which is "uno" 
3) a [phrase|frase] whith length [one|[uno|one]], which is "[uno|one]" 

我在這裏看到了兩個問題:

  • word phrase is bei ng而不是a phrase。我認爲這可以通過長度排序字典來解決,優先考慮較長的條款。
  • 已經被替換的單詞正在被重新替換,如uno[one|uno]。我想過使用某種正則表達式列表(與Regex::union),但我不知道它將如何高效和清潔。

任何想法?

回答

2

要解決您的第二個問題,您必須在一次更換。

按照您提到的順序將字典轉換爲具有鍵值對的哈希(可能按長度排序)。

dictionary = { 
    "a phrase" => "[a phrase|una frase]", 
    "phrase" => "[phrase|frase]", 
    "one" => "[one|uno]", 
    "uno" => "[uno|one]", 
} 

然後全部替換一次。

text.gsub(Regexp.union(*dictionary.keys.map{|w| "\b#{w}\b"}), dictionary) 
+0

我雖然這個解決方案,並且我gratefull你發佈了一個片段。但是,我不知道'Regex :: union'有多高效。也許我會稍後做一個基準測試,在字典上測試一千個字詞,用一個2k字長的文件進行測試。謝謝! – Wikiti

+0

如果你可以限制模式,比如'/ \ b \ w +?\ w + /',那麼你不需要使用'Regexp.union'。 – sawa

+0

條款可能含有未定義的字數。我無法以這種方式簡化正則表達式。 – Wikiti