我使用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"
答案 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
表示"字边界"。我已经放置了两个字符串的每一边。 此解决方案假定str1
和str2
都是单个词。 (如果它们包含空格,那么我不知道你期望的行为?)\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"
。但也许它应该实际上:
"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;。我已经放置了两个字符串的每一边。 此解决方案假定str1
和str2
都是单个词。 (如果它们包含空格,那么我不知道你期望的行为?)\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.)*
是收集每个字符,一次一个,总是检查它不是单词的第一个字母(即由非单词边界继续)。