Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby正则表达式(regex):字符最多只出现一次_Ruby_Regex - Fatal编程技术网

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

Ruby正则表达式(regex):字符最多只出现一次,ruby,regex,Ruby,Regex,假设我想确保字符串x等于abcd的任意组合(每个字符出现一次或零次-->每个字符不应重复,但组合可能以任何顺序出现) 有效日期:bc。。abcd。。。bcad。。。BD直流电 无效例如abcdd、cc、bbbb、abcde(当然) 我的努力: 我尝试了各种技巧: 最近的一次是 x=^((a)-(b)-(c)-(d))$ 但是,如果我没有按照我写的顺序键入它们,这将不起作用: 工作对象:ab、acd、abcd、a、d、c 不适用于:bcda、cb、da(不在上述顺序中的任何内容) 您可以在此处测试

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

  • 有效日期:bc。。abcd。。。bcad。。。BD直流电
  • 无效例如abcdd、cc、bbbb、abcde(当然)
  • 我的努力: 我尝试了各种技巧: 最近的一次是 x=^((a)-(b)-(c)-(d))$

    但是,如果我没有按照我写的顺序键入它们,这将不起作用:

  • 工作对象:ab、acd、abcd、a、d、c
  • 不适用于:bcda、cb、da(不在上述顺序中的任何内容)
  • 您可以在此处测试您的解决方案:


    注:字符可能不是按字母顺序排列的,它可能是u c e t

    如果您可以使用正则表达式以外的东西,您可以尝试:

    str.chars.uniq.length == str.length && str.match(/^[a-d]+$/)
    
    这里的一般想法是,只需从字符串中删除任何重复的字符,如果uniq数组的长度不等于源字符串的长度,则字符串中有一个重复的字符。然后,正则表达式强制执行字符集

    这可能是可以改进的,但非常简单。它确实会创建几个额外的阵列,因此如果需要在性能关键的位置使用,您可能需要一种不同的方法

    如果要坚持使用正则表达式,可以使用:

    str.match(/^[a-d]+$/) && !str.match(/([a-d]).*\1/)
    

    这将基本上检查字符串是否只包含允许的字符,并且这些字符从不重复。

    这实际上不是正则表达式要做的,但是如果您真的想做的话

    下面是一个满足条件的正则表达式

    ^([a-d])(?!(\1))([a-d])?(?!(\1|\3))([a-d])?(?!(\1|\3|\5))([a-d])?(?!(\1|\3|\5|\7))$
    

    基本上,它会遍历每个角色,组成一个组,然后确保该组不匹配。然后检查下一个字符,确保该组和前面的组不匹配。

    我认为正则表达式不适合这个问题,所以这里有另一个非正则表达式的解决方案。它是递归的:

    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]
    
    您可以将其反转(匹配使其失败的条件)


    在您的示例中,bcab是有效的。你的意思是让b重复吗?根据你其余的描述,我认为那是无效的。是的,那是我的错。谢谢,我有两个打字错误,遗漏了一些
    |
    。现在修复,它不匹配
    “acd”
    。呸,我没看到它应该匹配lessOk,修订版。。。再次说明:)可以使用少于4个字符,现在请再次执行,但让我们看看
    a-g
    的外观。我喜欢这个,因为它很简洁。但是,对于大字符串来说,这并不是最理想的。如果您只需要小写字母字符串,则可以自动删除任何长度超过26个字符的字符串,因为它必须重复一个字符。如果要匹配的字符集包含重复项,则输入可以超过26个字符;)是的,但您知道任何长度大于26个字符的字符串都必须包含重复项,因此您可以将其视为有效而拒绝,而无需对其进行任何进一步的分析。通过确保只需对小字符串执行更昂贵的操作,就可以解决“大字符串”问题。那么,最大字符串长度就是有效字符集的大小。Unicode“仅”有95221个有效字符-数组操作即使在这种大小的字符串上也能快速运行。对于四个字符来说,这是合理的,但更大的允许字符集将真正结束堆栈。想象一下,如果允许使用Unicode字符集,会发生什么情况。这个算法一点也不好用!这个问题本质上是关于面包屑搜索的一个变体。正如这里所证明的,有许多方法,每种方法都有强制权衡的隐含假设。在我看来,这就是答案有趣的原因。
    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}