如果用户仅输入一组可能的匹配项中的一个,我想返回true。与XOR运算符类似,但整个组中只有一个字符串可能存在于输入中。这是我的代码:
if input.match?(/str|con|dex|wis|int|cha/)
以下input
应该返回true:
+2 int
-3con
str
con
wisdom
dexterity
以下input
应当返回false:
+1 int +2 cha
-4dex+3con-1cha
int cha
str dex
con wis cha
strength intelligence
strdex
答案 0 :(得分:7)
我可能会使用String#scan
和一个简单的正则表达式,以便您以后可以了解自己所做的事情:
if input.scan(/str|dex|con|int|wis|cha/).length == 1
# Found exactly one
else
# Didn't find it or found too many
end
这也使得区分失败的方式变得更加容易。
大概您的字符串会比较小,因此扫描字符串以查找所有匹配项不会有任何明显的开销。
答案 1 :(得分:5)
以下是在不创建中间数组的情况下回答问题的三种方法。都使用正则表达式:
R = /str|con|dex|wis|int|cha/
并返回以下内容:
one_match? "It wasn't a con, really" #=> true
one_match? "That sounds to me like a wild guess." #=> falsy (nil or false)
one_match? "Both int and dex are present." #=> falsy (nil or false)
one_match? "Three is an integer." #=> true
one_match? "Both int and indexes are present." #=> falsy (nil or false)
#1第一场和最后一场比赛是否从同一索引开始?
def one_match?(s)
(idx = s.index(R)) && idx == s.rindex(R)
end
请参见String#index和String#rindex。
#2使用String#index
的形式,其参数等于开始搜索的索引。
def one_match?(s)
s.index(R) && s.index(R, Regexp.last_match.end(0)).nil?
end
请参见Regexp::last_match和MatchData#end。 Regexp.last_match
可以替换为$~
。
#3使用String#gsub的形式,该形式采用一个参数且没有任何块,以创建一个生成匹配项的枚举器
def one_match?(s)
s.gsub(/str|con|dex|wis|int|cha/).count { true } == 1
end
请参见Enumerable#count。
仅匹配整个单词
在倒数第二个示例中,'int'
与'int'
中的'integer'
匹配,在最后一个匹配中,'dex'
与'dex'
中的'indexes'
匹配。要执行全字匹配,可以将正则表达式更改为:
/\b(?:str|con|dex|wis|int|cha)\b/
答案 2 :(得分:3)
如果必须使用正则表达式,则可以使用
/\A(?!(?:.*(str|con|dex|wis|int|cha)){2}).*\g<1>/m
请参见regex demo
详细信息
\A
-字符串的开头(?!(?:.*(str|con|dex|wis|int|cha)){2})
-没有两次出现任何0+个字符,后跟str
,con
,dex
,wis
,int
,{ {1}} cha
-尽可能多的0个字符.*
-第1组模式(\g<1>
,str
,con
,dex
,wis
或int
)。