如何将 gsub 应用于函数?
How do I apply gsub subject to a function?
我正在使用 Rails 5 和 Ruby 2.4。我有一个函数
my_function(str1, str2)
给定两个字符串参数,return 为真或假。我想做的是给一个更大的字符串,例如
"a b c d"
如果表达式
,我想用空字符串替换两个连续的 "words"(根据我的定义,一个词是一系列字符后跟一个词边界)
my_function(str1, str2)
对于这两个连续的单词计算结果为真。例如,如果
my_function("b", "c")
计算结果为真,我希望上面的字符串变成
"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"
编辑: 这是根据以下评论更新的答案。我把原来的答案留在了底部。
扫描 "two consecutive words" 的字符串有点棘手。您最好的选择可能是在正则表达式中使用 \b
锚点,它表示 "word boundary":
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"]]
...第一个字符串是 "full match"(包括任何空格或标点符号),其他是两个单词。
分解正则表达式:
\b
表示 "word boundary"。我在两根弦的每一侧都放了一根。 此解决方案假定 str1
和 str2
都是一个单词 。 (如果它们包含空格,那么我不知道您期望什么行为?)
\S+?
表示 "one or more non-whitespace character"。 (非贪婪匹配,所以会在first字边界处停止匹配)。
然后您可以从字符串中删除每个 "full match",如果方法 returns 对两个单词为真:
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)
returns 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
表示 "word boundary"。我在两根弦的每一侧都放了一根。 此解决方案假定 str1
和 str2
都是一个单词 。 (如果它们包含空格,那么我不知道您期望什么行为?)
\s+
表示 "one or more whitespace character"。您可能希望对此进行调整以允许使用其他标点符号,例如逗号或句号。这个问题的一个完全通用的解决方案实际上可能是:
.
string_to_change.gsub!(/\b#{str1}\b.(\B.)*#{str2}\b/, "")
# Or equivalently:
string_to_change.gsub!(/\b#{str1}\b(.\B)*.#{str2}\b/, "")
.(\B.)*
而是收集每个字符,一次一个,始终检查它不是单词的第一个字母(即以非单词边界开头)。
我正在使用 Rails 5 和 Ruby 2.4。我有一个函数
my_function(str1, str2)
给定两个字符串参数,return 为真或假。我想做的是给一个更大的字符串,例如
"a b c d"
如果表达式
,我想用空字符串替换两个连续的 "words"(根据我的定义,一个词是一系列字符后跟一个词边界)my_function(str1, str2)
对于这两个连续的单词计算结果为真。例如,如果
my_function("b", "c")
计算结果为真,我希望上面的字符串变成
"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"
编辑: 这是根据以下评论更新的答案。我把原来的答案留在了底部。
扫描 "two consecutive words" 的字符串有点棘手。您最好的选择可能是在正则表达式中使用 \b
锚点,它表示 "word boundary":
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"]]
...第一个字符串是 "full match"(包括任何空格或标点符号),其他是两个单词。
分解正则表达式:
\b
表示 "word boundary"。我在两根弦的每一侧都放了一根。 此解决方案假定str1
和str2
都是一个单词 。 (如果它们包含空格,那么我不知道您期望什么行为?)\S+?
表示 "one or more non-whitespace character"。 (非贪婪匹配,所以会在first字边界处停止匹配)。
然后您可以从字符串中删除每个 "full match",如果方法 returns 对两个单词为真:
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)
returns 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
表示 "word boundary"。我在两根弦的每一侧都放了一根。 此解决方案假定str1
和str2
都是一个单词 。 (如果它们包含空格,那么我不知道您期望什么行为?)\s+
表示 "one or more whitespace character"。您可能希望对此进行调整以允许使用其他标点符号,例如逗号或句号。这个问题的一个完全通用的解决方案实际上可能是:
.
string_to_change.gsub!(/\b#{str1}\b.(\B.)*#{str2}\b/, "")
# Or equivalently:
string_to_change.gsub!(/\b#{str1}\b(.\B)*.#{str2}\b/, "")
.(\B.)*
而是收集每个字符,一次一个,始终检查它不是单词的第一个字母(即以非单词边界开头)。