如何根据Ruby中Array中的单词替换字符串中的单词?

时间:2016-10-19 17:01:25

标签: ruby-on-rails ruby

我该怎么办?我尝试过这个gsub,但是如果strings_to_highlight数组很大,我无法弄清楚它真正有效。干杯!

  string = "Roses are red, violets are blue"

  strings_to_highlight = ['red', 'blue']

  # ALGORITHM HERE

  resulting_string = "Roses are (red), violets are (blue)"

4 个答案:

答案 0 :(得分:5)

Regexp有一个有用的union函数,用于将正则表达式组合在一起。坚持使用正则表达式,直到遇到性能问题:

string = "Roses are red, violets are blue"
strings_to_highlight = ['red', 'blue']

def highlight(str, words)
  matcher = Regexp.union words.map { |w| /\b(#{Regexp.escape(w)})\b/ }
  str.gsub(matcher) { |word| "(#{word})" }
end

puts highlight(string, strings_to_highlight)

答案 1 :(得分:4)

strings_to_highlight = ['red', 'blue']
string = "Roses are red, violets are blue"

strings_to_highlight.each { |i| string.gsub!(/\b#{i}\b/, "(#{i})")}

答案 2 :(得分:2)

我建议使用String#gsub的形式,使用哈希进行替换。

strings_to_highlight = ['red', 'blue']

首先构造哈希。

h = strings_to_highlight.each_with_object({}) do |s,h|
  h[s] = "(#{s})"
  ss = "#{s[0].swapcase}#{s[1..-1]}"
  h[ss] = "(#{ss})"
end
  #=> {"red"=>"(red)", "Red"=>"(Red)", "Blue"=>"(Blue)", "blue"=>"(blue)"} 

接下来为它定义一个默认的proc:

h.default_proc = ->(h,k) { k }

因此如果h没有密钥kh[k]会返回k(例如h["cat"] #=> "cat")。

准备好了!

string = "Roses are Red, violets are blue"

string.gsub(/[[[:alpha:]]]+/, h)
 => "Roses are (Red), violets are (blue)"

这应该是相对有效的,因为只需要通过字符串一次并且哈希查找非常快。

答案 3 :(得分:1)

我会用:

string = "Roses are red, violets are blue"
strings_to_highlight = ['red', 'blue']

string.gsub(/\b(#{Regexp.union(strings_to_highlight).source})\b/) { |s| "(#{s})" } # => "Roses are (red), violets are (blue)"

以下是它如何分解:

/\b(#{Regexp.union(strings_to_highlight).source})\b/ # => /\b(red|blue)\b/

嵌入模式时使用source非常重要。没有它会导致:

/\b(#{Regexp.union(strings_to_highlight)})\b/ # => /\b((?-mix:red|blue))\b/

如果您不理解regex-ese中的含义,(?-mix:...)部分可能会导致问题。 Regexp文档解释了这些标志,但是如果你不知道这个问题,那么如果没有这样做就会导致很难诊断错误。

\b告诉引擎匹配单词,而不是子串。没有它,你最终可能会:

string = "Fred, bluette"
strings_to_highlight = ['red', 'blue']
string.gsub(/(#{Regexp.union(strings_to_highlight).source})/) { |s| "(#{s})" } 
# => "F(red), (blue)tte"

使用gsub的块允许我们对匹配的值执行计算。