假设我想确保字符串x等于abcd的任何组合(每个字符出现一次或零次 - >每个字符不应重复,但组合可能以任何顺序出现)
我的努力: 我尝试了各种技巧: 我最亲近的是 x =〜 ^(((a)?(b)?(c)?(d)?))$
但如果我不按照我写的顺序输入它们,那么这不会起作用:
您可以在此处测试您的解决方案:http://rubular.com/r/wCpD355bub
PS:字符可能不是按字母顺序排列,也可能是字符
答案 0 :(得分:5)
如果您可以使用除正则表达式之外的其他内容,您可以尝试:
str.chars.uniq.length == str.length && str.match(/^[a-d]+$/)
这里的一般想法是你只是从字符串中删除任何重复的字符,如果uniq数组的长度不等于源字符串的长度,则字符串中有一个重复的字符。然后正则表达式强制执行字符集。
这可能会有所改进,但它非常简单。它确实会创建一些额外的数组,因此如果需要在性能关键位置使用它,您可能需要采用不同的方法。
如果你想坚持正则表达式,你可以使用:
str.match(/^[a-d]+$/) && !str.match(/([a-d]).*\1/)
这基本上会检查字符串是否只包含允许的字符,并且这些字符永远不会重复。
答案 1 :(得分:4)
这不是正则表达式的意思,但如果你真的想要这样做。
这是一个满足条件的正则表达式。
^([a-d])(?!(\1))([a-d])?(?!(\1|\3))([a-d])?(?!(\1|\3|\5))([a-d])?(?!(\1|\3|\5|\7))$
基本上它遍历每个角色,制作组,然后确保该组不匹配。然后检查下一个字符,并确保该组和以前的组不匹配。
答案 2 :(得分:2)
您可以将其反转(匹配使其失败的条件)
re = /^ # start of line
(?=.*([a-d]).*\1) # match if a letter appears more than once
| # or
(?=.*[^a-d]) # match if a non abcd char appears
/x
puts 'fail' if %w{bc abcd bcad b d dc}.any?{|s| s =~ re}
puts 'fail' unless %w{abcdd cc bbbb abcde}.all?{|s| s =~ re}
答案 3 :(得分:1)
我认为正则表达式不适合这个问题,所以这是另一个非正则表达式解决方案。这是递归的:
def match_chars_no_more_than_once(characters, string)
return true if string.empty?
if characters.index(string[0])
match_chars_no_more_than_once(characters.sub(string[0],''), string[1..-1])
else
false
end
end
%w{bc bdac hello acbbd cdda}.each do |string|
p [string, match_chars_no_more_than_once('abcd', string)]
end
输出:
["bc", true]
["bdac", true]
["hello", false]
["acbbd", false]
["cdda", false]