正则表达式以任意随机顺序与单词的字符完全匹配,没有重复的字符

时间:2017-08-11 11:07:40

标签: java regex string random match

我们说我有一个字符串,我想检查它是否与任何可能的(随机)顺序中的另一个字符串匹配。例如,假设我有一个字符串s,我想检查它是否与随机顺序中的"ONE"匹配(==以下之一:ENO|EON|NEO|NOE|OEN|ONE,但不是EEE;EEN;EEO;等。)

在更一般的描述中:我正在寻找正则表达式以随机顺序匹配字符串,只有该字符串的给定字符(这意味着字符串本身可以包含重复字符,如{{1但是,应该在随机匹配中恰好使用两个SEVEN,而不是更多或更少。)

我知道我可以使用文字E来匹配ENO|EON|NEO|NOE|OEN|ONEONETWO也一样,但这太长了..
我也知道我可以匹配所有内容,包括像NINE这样的重复字符,但它也会错误地匹配[ONE]{3}EEE等。

我知道我也可以创建一个循环来生成所有这些不同的排列,并将它们与EEN分隔符一起追加。我认为在这种情况下,这也可能是一个有效的解决方案。但是,如果使用正则表达式这是可能的,我也想知道我自己的知识。哦,即使它有一个循环,我也不希望它太长(因为我实际上是因为代码 - 高尔夫挑战,你在哪里解决某个挑战在尽可能少的字节中。)

4 个答案:

答案 0 :(得分:4)

你可以把条件放在前瞻性。对于ONE:

\b(?=\w*O)(?=\w*N)(?=\w*E)[ONE]{3}\b

对于SEVEN:

\b(?=\w*S)(?=\w*E\w*E)(?=\w*V)(?=\w*N)[SEVN]{5}\b

为了提高大文本的性能,您可以测试模式开头的字母和长度:

\b(?=[ONE]{3}\b)(?=\w*O)(?=\w*N)\w*E\w*

或:

\b(?=[SEVN]{5}\b)(?=\w*S)(?=\w*E\w*E)(?=\w*V)\w*N\w*

这样,包含其他字母或单词的单词不会很快被丢弃。

您还可以在最后设置效率较低的条件:

\b(?=[SEVN]{5}\b)(?=\w*S)(?=\w*V)(?=\w*N)\w*E\w*E\w*

要完成,您还可以使用否定的字符类来减少回溯:

\b(?=[SEVN]{5}\b)(?=[^\WS]*S)(?=[^\WV]*V)(?=[^\WN]*N)[^\WE]*E[^\WE]*E\w*

或使用其他字母:

\b(?=[SEVN]{5}\b)(?=[EVN]*S)(?=[SEN]*V)(?=[SEV]*N)[SVN]*E[SVN]*E\w*

答案 1 :(得分:1)

我认为,正则表达式不能这样做。

使用map< Integer,Integer>来统计你的字符,并验证,或只是一个数组(更快)。

答案 2 :(得分:0)

是的,你可以构建你的正则表达式,使其像^(?=[ONE]{3}$)(?=.*O).*(?=.*N).*(?=.*E).*$ regex demo一样,所以你可以使用这样的东西:

public static void main(String[] args) {
    String[] strings = new String[]{"ENOE", "ENO", "EON", "NEO", "NOE", "OEN", 
        "ONE", "OOO"};
    Main m = new Main();
    String word = "ONE";// This can be any word you want to matche
    String regex = m.getPattern(word);
    System.out.println(regex);
    for (String s : strings) {
        if (s.matches(regex)) {
            System.out.println("matches : " + s);
        } else {
            System.out.println("Not matches : " + s);
        }
    }
}

// I use Java 8 to create the pattern it is more helpful
private String getPattern(String word) {
    StringBuilder pattern = new StringBuilder();
    //^(?=[ONE]{3}$)
    pattern.append("^(?=[").append(word).append("]{").append(word.length()).append("}$)");
    Arrays.asList(word.split("")).stream()
            .map(t -> "(?=.*" + t + ").*")
            .forEach(pattern::append);
    pattern.append("$");
    return pattern.toString();// result (?=.*O).*(?=.*N).*(?=.*E).*
}

<强>输出

Not matches : ENOE
matches : ENO
matches : EON
matches : NEO
matches : NOE
matches : OEN
matches : ONE
Not matches : OOO

答案 3 :(得分:0)

如果字符串中的字符是唯一的

,则可以使用以下正则表达式执行此操作
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
    <name>Foo</name>
    <comment></comment>
    <projects>
    </projects>
    <buildSpec>
        <buildCommand>
            <name>org.eclipse.jdt.core.javabuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
    </buildSpec>
    <natures>
        <nature>org.eclipse.jdt.core.javanature</nature>
    </natures>
</projectDescription>

您可以看到演示here

正则表达式的工作原理如下enter image description here

基本上它匹配一个3个字母的单词,由 [ONE] 中的字母组成,并确保所有3个单词出现在结果字符串中