使用正则表达式创建由四个不同字母组成的单词?

6
例如,reassesses将匹配。它包含完全不同的4个字符:'r'、'e'、'a'和's'。
我的尝试是:/^([a-z])([a-z])([a-z])([a-z])(\1|\2|\3|\4)(\1|\2|\3|\4)(\1|\2|\3|\4)$/(根据单词长度添加尽可能多的(\1|\2|\3|\4))。
然而,这只能匹配最多4个不同字母,并且只有它们是前4个字符时才能匹配。
有更好的解决方案吗?

1
我不会为此使用正则表达式。 - John Dvorak
1
Haskell: length (nub str) == 4。另一种解决方案:length (group $ sort str) == 4 - John Dvorak
我的电池现在没电了,但我回家后可能会写一个解决方案。 - John Dvorak
1
反向引用?真的吗!?我希望更多的时间花在创建可维护的代码上。随着每个正则表达式的使用,代码的可维护性都会降低,而使用反向引用则更加如此。 - makerofthings7
1
我希望你的教授能够来这里教育我们。我一定会对他的解决方案感到好奇。 - aliteralmind
显示剩余9条评论
4个回答

1
像这样的东西:
^([a-z])\1*+([a-z])(?:\1|\2)*+([a-z])(?:\1|\2|\3)*+([a-z])(?:\1|\2|\3|\4)*$

在这个模式中,使用占有量词是必不可少的,因为它禁止回溯并避免以下捕获组匹配已找到的字母。

占有量词功能在Java中可用(不要忘记双倍转义反向引用),但如果您需要在不具备此功能的语言中使用该模式,则可以在我的评论中找到几个“翻译”该模式的选项。

上述模式是构建用于检查整个字符串的,但如果您想在较大的字符串中查找单词,则可以使用此选项(可能带有大小写不敏感选项):

(?<![a-z])([a-z])\1*+([a-z])(?:\1|\2)*+([a-z])(?:\1|\2|\3)*+([a-z])(?:\1|\2|\3|\4)*(?![a-z])

如果唯一字符少于四个,这也符合条件。不过,可以通过负向先行断言来解决这个问题。 - John Dvorak
@JanDvorak:在这种情况下,拥有性量词更好。 - Casimir et Hippolyte
1
如果可用的话,最好提供两种选择(最好附带一些讨论和解释)。 - John Dvorak
我喜欢这个答案,即使没有解释。不过需要注意的是,它使用了所有格量词 *+,在 JavaScript(Chrome/IE)、C# 或 Python(2.7/3.3)中不能直接使用,需要进行修改。以下正则表达式可以使用:^([a-z])(?:\1*)+([a-z])(?:(?:\1|\2)*)+([a-z])(?:(?:\1|\2|\3)*)+([a-z])(?:\1|\2|\3|\4)*$ - Dean Taylor
@DeanTaylor:这个模式匹配“abca”。 (?:\1*)+\1*+略有不同(请参见http://www.regular-expressions.info/possessive.html了解更多信息)。 OP似乎使用Java,但您可以通过将\1*+替换为(?>\1*)来使其在C#中工作。 对于Javascript或Python的re模块,您可以将其替换为(?=(\1*))\2(?=((?:\1|\3)*))\4等。 - Casimir et Hippolyte

1

尝试

^([a-z])\1*([a-z])(\1*\2*)*([a-z])(\1*\2*\4*)*([a-z])(\1*\2*\4*\6*)*$

编辑以不匹配少于4个唯一字符(例如aaaa):

^([a-z])\1*(?!\1)([a-z])(\1*\2*)*(?!\1)(?!\2)([a-z])(\1*\2*\4*)*(?!\1)(?!\2)(?!\4)([a-z])(\1*\2*\4*\6*)*$

此外,这只匹配4个唯一的小写字母。要匹配4个唯一的字符,请将所有[a-z]替换为“.”。 - Khaelex
2
+1,但我会使用非捕获组来重复,这样反向引用的编号就从1到4:^([a-z])\1*([a-z])(?:\1*\2*)*([a-z])(?:\1*\2*\3*)*([a-z])(?:\1*\2*\3*\4*)*$ - Tim Pietzcker
2
如果少于四个唯一字符,这也会匹配。不过,负向先行断言可以解决这个问题。 - John Dvorak

1

绝对有效 -
这应该会导致仅由4个不同字符组成的对齐字符串,长度>= 4。

 #  ^(?=.*(.).*(?!\1)(.).*(?!\1|\2)(.).*(?!\1|\2|\3)(.))(?:\1|\2|\3|\4)+$

 ^ 
 (?=
      .* 
      ( . )
      .* 
      (?! \1 )
      ( . )
      .* 
      (?! \1 | \2 )
      ( . )
      .* 
      (?! \1 | \2 | \3 )
      ( . )
 )
 (?: \1 | \2 | \3 | \4 )+
 $ 

Perl测试用例:
if ("upepipipeu" =~ /^(?=.*(.).*(?!\1)(.).*(?!\1|\2)(.).*(?!\1|\2|\3)(.))(?:\1|\2|\3|\4)+$/)
{
      print "unique chars: '$1'  '$2'  '$3'  '$4'\n";
      print "matched:      '$&'\n";
}

输出 >>
unique chars: 'i'  'p'  'e'  'u'
matched:      'upepipipeu'

对 @aliteralmind 的测试用例:

@Ary = ("aabbccdd", "dictionary", "reassess", "aaaa");

for( @Ary )
{
    if ("$_" =~ /^(?=.*(.).*(?!\1)(.).*(?!\1|\2)(.).*(?!\1|\2|\3)(.))(?:\1|\2|\3|\4)+$/)
    {
       print "unique chars: '$1'  '$2'  '$3'  '$4'\n";
       print "matched:      '$&'\n\n";
    }
    else
    {
       print "Failed-> '$_'\n\n";
    }
}

输出 >>
unique chars: 'a'  'b'  'c'  'd'
matched:      'aabbccdd'

Failed-> 'dictionary'

unique chars: 'r'  'a'  'e'  's'
matched:      'reassess'

Failed-> 'aaaa'

@aliteralmind - 你从哪里得出它对于4个字符不起作用的结论?有一个测试案例,它是有效的。 - user557597
1
@aliteralmind - 我在测试用例中发布了这些字符串。你对结果有异议吗?正则表达式每次都强制执行正确的解决方案。 - user557597

0

就正则表达式而言,这是一个令人头痛的问题。这里提供一种非正则表达式的解决方案。该函数使用映射来跟踪唯一字符,并在达到最大唯一字符数时返回true。

import  java.util.Map;
import  java.util.TreeMap;

/**
   <P>{@code java ExactlyFourDiffChars}</P>
 **/
public class ExactlyFourDiffChars  {
   public static final void main(String[] ignored)  {
      System.out.println("aabbccdd: " + hasMoreThanXUniqueChars(4, "aabbccdd"));
      System.out.println("dictionary: " + hasMoreThanXUniqueChars(4, "dictionary"));
      System.out.println("reassesses: " + hasMoreThanXUniqueChars(4, "reassesses"));
   }
   public static final boolean hasMoreThanXUniqueChars(int maxAllowedChars, String str)  {
      Map<Character,Object> charMap = new TreeMap<Character,Object>();

      for(int i = 0; i < str.length(); i++)  {
         Character C = str.charAt(i);
         if(!charMap.containsKey(C))  {
            charMap.put(C, null);

            if(maxAllowedChars-- == 0)  {
               return  false;
            }
         }
      }
      return  true;
   }
}

输出:

[C:\java_code\]java ExactlyFourDiffChars
aabbccdd: true
dictionary: false
reassesses : true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接