Ruby正则表达式(正则表达式):字符最多只出现一次

时间:2013-06-07 22:05:44

标签: ruby regex

假设我想确保字符串x等于abcd的任何组合(每个字符出现一次或零次 - >每个字符不应重复,但组合可能以任何顺序出现)

  1. 有效的ex:bc .. abcd ... bcad ... b ... d .. dc
  2. 无效的前。 abcdd,cc,bbbb,abcde(ofcourse)
  3. 我的努力: 我尝试了各种技巧: 我最亲近的是 x =〜 ^(((a)?(b)?(c)?(d)?))$

    但如果我不按照我写的顺序输入它们,那么这不会起作用:

    1. 适用于:ab,acd,abcd,a,d,c
    2. 不适用于:bcda,cb,da(任何不符合上述顺序的内容)
    3. 您可以在此处测试您的解决方案:http://rubular.com/r/wCpD355bub

      PS:字符可能不是按字母顺序排列,也可能是字符

4 个答案:

答案 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]