编辑:这是一个更新的答案,根据下面的评论。我已将原始答案留在底部。
扫描“两个连续单词”的字符串有点棘手。你最好的选择可能是使用\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"
也应该被删除?
如果需要进一步改进,请在新问题中清楚解释它们(如果您正在努力自己解决问题)。
原来的答复:
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
手段 “单词边界”。我已经放置了两个字符串的每一边的一个。 此解决方案假定str1
和str2
都是单个词。 (如果它们包含空格,那么我不知道你期望什么行为?)
\s+
表示“一个或多个空格字符”。你可能希望调整它以允许其他标点符号,例如逗号或句号。这个问题的完全通用的解决方案实际上可以是:
。
string_to_change.gsub!(/\b#{str1}\b.(\B.)*#{str2}\b/, "")
# Or equivalently:
string_to_change.gsub!(/\b#{str1}\b(.\B)*.#{str2}\b/, "")
.(\B.)*
代替收集每个字符,一次一个,总是检查它不是一个字的第一个字母(即由非单词边界进行)。
这是一个'if'语句,而不是一个方法。是的你可以。 –
(只要你首先定义'my_function'方法,并使其返回'true'),尝试在控制台中运行它。它工作正常。 –
谢谢你,但你已经在你的解决方案中硬编码了几个东西。我只是列举“b”和“c”为例。有一些参数可能会导致my_function(str1,str2)为true。如果我只给了一长串文字呢?那么我如何才能使逻辑工作? – Dave