如何将gsub主题应用于某个函数?

时间:2017-10-11 15:02:39

标签: ruby string gsub

我使用Rails 5和Ruby 2.4。我有一个功能

my_function(str1, str2)

在给定两个字符串参数的情况下返回true或false。我想要做的是给出一个更大的字符串,例如

"a   b   c d"

我想替换两个连续的"单词" (我的定义是一个字符序列后跟一个单词边界),如果是表达式

,则为空字符串
my_function(str1, str2)
对于这两个连续的单词,

的计算结果为true。例如,如果

my_function("b", "c") 

评估为true,我希望上面的字符串成为

"a    d"

我该怎么做?

编辑:我包括基于Tom Lord回答的输出......

如果我使用

  def stuff(line)
    matches = line.scan(/\b((\S+?)\b.*?\b(\S+?))\b/)
    matches.each do |full_match, word1, word2|
      line.delete!(full_match) if word1.eql?("hello") && word2.eql?("world") 
    end
  end

和行是

"hello world this is a test"

结果字符串行是

"tisisatst"

这不是我的预期。结果应该是

" this is a test"

1 个答案:

答案 0 :(得分:2)

修改:这是根据以下评论更新的答案。我把原来的答案留在了最底层。

扫描字符串"连续两个字"有点棘手。您最好的选择可能是在正则表达式中使用\b锚点,这表示"字边界":

string_to_change = "a   b   c d"

matches = string_to_change.scan(/\b((\S+?)\b.*?\b(\S+?))\b/)
  # => [["a   b", "a", "b"], ["c d", "c", "d"]]

...第一个字符串是"完全匹配" (包括任何空格或标点符号),其他是两个字。

打破正则表达式:

  • \b表示"字边界"。我已经放置了两个字符串的每一边。 此解决方案假定str1str2都是单个词。 (如果它们包含空格,那么我不知道你期望的行为?)
  • \S+?表示"一个或多个非空白字符"。 (非贪婪匹配,因此它会在第一个字边界处停止匹配)。

然后你可以删除每个"完全匹配"从字符串中,如果该方法对两个单词返回true:

matches.each do |full_match, word1, word2|
  string_to_change.gsub!(full_match, '') if my_function(word1, word2)
end

例如,请考虑以下事项:

"hello world this is a test"

假设my_function(word1, word2)仅针对对true"world", "this"返回"hello", "is"

我上面的代码只会 查看对:"hello", "world""this", "is""a", "test"。但也许它应该实际上:

  1. 查看所有对单词,即匹配左侧和右侧的所有单词。
  2. 删除重复字词对,即删除初始对:"world this"后,应重新扫描该字符串,然后还应移除"hello is"?< / LI>

    如果需要进一步增强,请在新问题中清楚解释(如果您正在努力解决问题)。

    原始回答:

    str1 = "b"
    str2 = "c"
    string_to_change = "a   b   c d"
    
    if my_function(str1, str2)
      string_to_change.gsub!(/\b#{str1}\b\s+\b#{str2}\b/, "")
    end
    

    打破正则表达式:

    • \b表示&#34;字边界&#34;。我已经放置了两个字符串的每一边。 此解决方案假定str1str2都是单个词。 (如果它们包含空格,那么我不知道你期望的行为?)
    • \s+表示&#34;一个或多个空白字符&#34;。您可能希望调整此项以允许其他标点符号,例如逗号或句号。这个问题的完全通用的解决方案实际上可能是:

    string_to_change.gsub!(/\b#{str1}\b.(\B.)*#{str2}\b/, "")
    
    # Or equivalently:
    
    string_to_change.gsub!(/\b#{str1}\b(.\B)*.#{str2}\b/, "")
    

    .(\B.)*是收集每个字符,一次一个,总是检查它不是单词的第一个字母(即由非单词边界继续)。