0

所以问题是确定字符串中的每个字符是否都包含在特定正则表达式的匹配中。或者,换一种说法,如果可以包含在特定正则表达式的某些匹配中的所有字符位置的集合包括字符串中的所有字符位置。

我的想法是做这样的事情:

boolean matchesAll(String myString, Matcher myMatcher){
    boolean matched[] = new boolean[myString.size()];
    for(myMatcher.reset(myString); myMatcher.find();)
        for(int idx = myMatcher.start(); idx < myMatcher.end(); idx++)
            matched[idx] = true;

    boolean allMatched = true;
    for(boolean charMatched : matched)
        allMatched &= charMatched;

    return allMatched
}

但是,有没有更好的方法来做到这一点?

另外,当我写这篇文章时,我突然想到,在像这样的情况下,这不会做我想要的

matchesAll("abcabcabc", Pattern.compile("(abc){2}").matcher()); //returns false

因为Matcher只尝试在最后一场比赛结束时开始匹配。我希望它返回 true,因为如果您在位置 3 开始匹配器,它可能会abc在匹配中包含第三个。

boolean matchesAll(String myString, Matcher myMatcher){

    boolean matched[] = new boolean[myString.size()];
    boolean allMatched = true;

    for(int idx = 0; idx < myString.size() && myMatcher.find(idx);
            idx = myMatcher.start() + 1) {

        for(int idx2 = myMatcher.start(); idx2 < myMatcher.end(); idx2++)
            matched[idx2] = true;
    }

    boolean allMatched = true;
    for(boolean charMatched : matched)
        allMatched &= charMatched;

    return allMatched;
}

有什么方法可以让这段代码更好、更快或更易读吗?

4

2 回答 2

2

我有 2 个答案给你,虽然我不确定我是否正确理解了这个问题。

  1. 调用 Pattern.matcher(str2match).matches() 方法而不是 find()。在一个镜头中,一个真正的返回值会告诉你整个字符串是否匹配。
  2. 在正则表达式前面加上“^”(字符串的开头),并在“Pattern.compile(str)”之前的末尾添加一个“$”(用于字符串的结尾) - 正则表达式。

这两种解决方案也可以一起使用。下面是一个示例类 - 您可以将其复制到 AllMatch.java 中,使用“javac AllMatch.java”编译它并作为“java AllMatch”运行(我假设您的 CLASSSPATH 中有“.”)。只需选择您认为更优雅的解决方案 :) 新年快乐!

import java.util.regex.Pattern;

公共类 AllMatch {

private Pattern pattern;

public AllMatch (String reStr) {
    pattern = Pattern.compile ("^" + reStr + "$");
}

public boolean checkMatch (String s) {
    return pattern.matcher(s).matches();
}

    public static void main (String[] args) {
    int n = args.length;
    String  rexp2Match = (n > 0) ? args[0] : "(abc)+",
        testString = (n > 1) ? args[1] : "abcabcabc",
        matchMaker = new AllMatch (rexp2Match)
                .checkMatch(testString) ? "" : "un";
    System.out.println ("[AllMatch] match " + matchMaker +
                "successful");
    }

}

于 2013-01-01T17:47:59.463 回答
1

这有效:

private static boolean fullyCovered(final String input,
    final Pattern pattern)
{
    // If the string is empty, check that it is matched by the pattern
    if (input.isEmpty())
        return pattern.matcher(input).find();

    final int len = input.length();
    // All initialized to false by default
    final boolean[] covered = new boolean[len];

    final Matcher matcher = pattern.matcher(input);

    for (int index = 0; index < len; index++) {
        // Try and match at this index:
        if (!matcher.find(index)) {
            // if there isn't a match, check if this character is already covered;
            // if no, it's a failure
            if (!covered[index])
                return false;
            // Otherwise, continue
            continue;
        }
        // If the match starts at the string index, fill the covered array
        if (matcher.start() == index)
            setCovered(covered, index, matcher.end());
    }

    // We have finished parsing the string: it is fully covered.
    return true;
}

private static void setCovered(final boolean[] covered,
    final int beginIndex, final int endIndex)
{
    for (int i = beginIndex; i < endIndex; i++)
        covered[i] = true;
}

执行起来可能不会更快,但我想它更容易阅读;)另外,.find(int)重置匹配器,所以这是安全的。

于 2013-01-01T17:53:41.240 回答