我想强制执行4个不同的字符。
有效示例:
"1q2w3e4r5t"
"abcd"
无效的例子:
"good"
"1ab1"
模式的想法?
答案 0 :(得分:3)
您应该考虑使用非正则表达式解决方案。我只写这个答案,为这个问题展示一个更简单的正则表达式解决方案。
这是一个更简单的正则表达式解决方案,它断言字符串中至少有4个不同的字符:
(.).*?((?!\1).).*?((?!\1|\2).).*?((?!\1|\2|\3).).*
Demo on regex101(PCRE和Java对此正则表达式具有相同的行为)
.*?((?!\1).)
,.*?((?!\1|\2).)
,...搜索之前未出现的下一个字符,通过检查字符与先前捕获组中捕获的字符不同来实现。< / p>
逻辑上,量词的懒惰/贪婪在这里并不重要。惰性量词.*?
用于使搜索从之前未出现的最接近的字符开始,而不是从最远的字符开始。它应该稍微改善匹配情况下的性能,因为减少了回溯。
与String.matches()
一起使用,它声明整个字符串与正则表达式匹配:
input.matches("(.).*?((?!\\1).).*?((?!\\1|\\2).).*?((?!\\1|\\2|\\3).).*")
如果您担心表现:
(.)(?>.*?((?!\1).))(?>.*?((?!\1|\2).))(?>.*?((?!\1|\2|\3).)).*
使用String.matches()
:
input.matches("(.)(?>.*?((?!\\1).))(?>.*?((?!\\1|\\2).))(?>.*?((?!\\1|\\2|\\3).)).*")
(?>pattern)
构造一旦退出内部模式,就会阻止回溯到组中。这用于将捕获组“锁定”到每个不同字符的第一个外观,因为即使您在字符串中稍后选择不同的字符,结果也是相同的。
这个正则表达式的行为与从左到右循环的普通程序相同,它会根据一组不同的字符检查当前字符,如果当前字符不在集合中,则将其添加到集合中。
由于这个原因,延迟量词.*?
变得很重要,因为它搜索到目前为止尚未出现的最接近的字符。
答案 1 :(得分:1)
您可以像这样计算不同字符的数量:
String s = "abcdefaa";
long numDistinctChars = s.chars().distinct().count()
或者如果不是在Java 8上(我无法想出更好的东西):
Set<Character> set = new HashSet<>();
char[] charArray = s.toCharArray();
for (char c : charArray) {
set.add(Character.valueOf(c));
}
int numDistinctChars = set.size();
答案 2 :(得分:1)
您可以使用正则表达式来验证这一点,使用负面预测来检查捕获的字母数字字符是否相同4次。
我会说这很难看,但是工作:
String rx = "^(.).*?((?!\\1).).*?((?!\\1|\\2).).*?((?!\\1|\\2|\\3).).*?$"
请参阅demo
String re = "^(.).*?((?!\\1).).*?((?!\\1|\\2).).*?((?!\\1|\\2|\\3).).*?$";
// Good
System.out.println("1q2w3e4r5t".matches(re));
System.out.println("goody".matches(re));
System.out.println("gggoooggoofr".matches(re));
// Bad
System.out.println("good".matches(re));
System.out.println("1ab1".matches(re));
输出:
true
true
true
false
false