正则表达式中没有重复的字母

时间:2018-03-22 12:54:06

标签: java regex

我对一个问题很难过。

这个问题需要一个缺少字母的线索。有一系列单词要与线索匹配,但是,如果单词中没有来自线索的字母,则该单词应该匹配。

我正在使用正则表达式,它匹配匹配的所有实例,但我无法弄清楚如何排除单词中包含重复字母的那些 名单。

例如,线索是aba???因此,abaton应该匹配,但abatua不应该匹配,因为两个单词中都有a,而且线索部分被掩盖了???

这是我的代码:

import java.util.ArrayList;

public class MatchTest {

    public ArrayList<String> wordLookup(ArrayList<String> wordList, String clue) {
        ArrayList<String> arrayList = new ArrayList<>();

        String regex = clue.replaceAll("\\?", "\\.?");

        for (int i = 0; i < wordList.size(); i++) {
            if (wordList.get(i).matches(regex)) {
                arrayList.add(wordList.get(i));
            }
        }
        return arrayList;
    }
}

    class MatchTestMain {
        public static void main(String[] args) {
            MatchTest mt = new MatchTest();
            ArrayList<String> wordList = new ArrayList<String>();

            wordList.add("abandon");
            wordList.add("wanton");
            wordList.add("abaton");
            wordList.add("abator");
            wordList.add("abatua");

            System.out.println(mt.wordLookup(wordList, "aba???"));
        }
}

我收到了这个输出

[abaton, abator, abatua]

但正确的输出是

[abaton, abator]

有什么想法吗?

编辑完整性:我找到了一个边缘情况,其中线索是全部?例如,线索是??????,它会导致线程“main”中的异常java.util.regex.PatternSyntaxException:Unclosed character [^]

我扩展了@Malte Hartwig提出的解决边缘案例的解决方案。

以下是最终版本:

import java.util.ArrayList;

public class MatchTest {

    public ArrayList<String> wordLookup(ArrayList<String> wordList, String clue) {
        ArrayList<String> arrayList = new ArrayList<>();

        String givenLetters = clue.replaceAll("\\?", "");
        String regex = clue.replaceAll("\\?", "\\[^" + givenLetters + "]");
        String regex2 = clue.replaceAll("\\?", "\\.?");

        if (givenLetters.length() == 0) {
            for (int i = 0; i < wordList.size(); i++) {
                if (wordList.get(i).matches(regex2) && wordList.get(i).length() == clue.length()) {
                    arrayList.add(wordList.get(i));
                }
            }
        }

        if (givenLetters.length() > 0) {
            for (int i = 0; i < wordList.size(); i++) {
                if (wordList.get(i).matches(regex)) {
                    arrayList.add(wordList.get(i));
                }
            }
        }
        return arrayList;
    }
}

    class MatchTestMain {
        public static void main(String[] args) {
            MatchTest mt = new MatchTest();
            ArrayList<String> wordList = new ArrayList<>();

            wordList.add("abandon");
            wordList.add("wanton");
            wordList.add("abaton");
            wordList.add("abator");
            wordList.add("abatua");

            System.out.println(mt.wordLookup(wordList, "ab??o?"));
            System.out.println(mt.wordLookup(wordList, "?b????"));
            System.out.println(mt.wordLookup(wordList, "abatua"));
            System.out.println(mt.wordLookup(wordList, "a?a???"));
            System.out.println(mt.wordLookup(wordList, "?ridge"));
            System.out.println(mt.wordLookup(wordList, "aba???"));
            System.out.println(mt.wordLookup(wordList, "??????"));
        }
}

输出:

[]
[abaton, abator, abatua]
[abatua]
[abaton, abator]
[]
[abaton, abator]
[wanton, abaton, abator, abatua]

2 个答案:

答案 0 :(得分:2)

您可以先提取线索中给出的字母列表:

String givenLetters = clue.replaceAll("\\?", "");
// givenLetters = "aba"

如果您在正则表达式中使用该列表,则可以将掩盖的字符告知其中一个字母:

String regex = clue.replaceAll("\\?", "\\[^" + givenLetters + "]");
// regex = "aba[^aba][^aba][^aba]";

这会在您的示例中替换.? [^aba],意思是&#34;不是ab&#34; (或a,在这种情况下无关紧要)。

它也应该适用于最后不只有?的线索,例如??a?b?,这会导致pattern = [^ab][^ab]a[^ab]b[^ab]

答案 1 :(得分:-1)

在您的程序中进行了一些更改...正在提供所需的输出

package testProgram;

            import java.util.ArrayList;

            class MatchTest {
            public ArrayList<String> wordLookup(ArrayList<String> wordList, String clue) {
                ArrayList<String> arrayList = new ArrayList<>();

                // String regex = clue.replaceAll("\\?", "\\.?");

                for (int i = 0; i < wordList.size(); i++) {
                    if (wordList.get(i).matches(clue)) {
                        arrayList.add(wordList.get(i));
                    }
                }
                return arrayList;
            }

        }

        public class MatchTestMain {
            public static void main(String[] args) {
                MatchTest mt = new MatchTest();
                ArrayList<String> wordList = new ArrayList<String>();

                wordList.add("abandon");
                wordList.add("wanton");
                wordList.add("abaton");
                wordList.add("abator");
                wordList.add("abatua");

                System.out.println(mt.wordLookup(wordList, "(aba)[^aba]{0,3}"));
            }
        }

(aba)[^ aba] {0,3}表示前3个字符将保持不变(aba)休息0-3个字符不包含这3个中的任何字符,即(aba)。

{0,3}表示至少为0且最多为3个字符。