2

我正在尝试编写一种方法来扫描字符串中的某些字符,并报告找到了哪些(如果有的话):

// Special characters are ~, #, @, and *
// If text == "Hello~Clarice, you're s#o ambitious", then this
// method should return a string == "~#". If no special characters
// found, return null. If the same special character occurs 2+ times,
// ignore it and do not return strings with duplicate special chars, like
// "##@***", etc. --> just "#@*".
public String detectAndGetSpecialCharacters(String text) {
    Pattern p = Pattern.compile("[~#@*]");
    Matcher m = pattern.matcher(text);

    String specialCharactersFound = null;
    if(m.find()) {
        // ???
    }

    return specialCharactersFound;
}

我已经完成了这个方法的检测部分,但我正在努力寻找一种有效/优雅的方法Matcher来告诉我找到了哪些特殊字符,此外,将它们连接在一起(删除重复项!)并返回它们。提前致谢!

4

3 回答 3

4

为什么不简单地使用String.indexOf(specialChar). 如果结果 >= 0,则为每个特殊字符调用此方法,这意味着该特殊字符至少存在一次。

然后根据找到的索引对特殊字符进行排序以构建解析字符串。

不是很优雅,但我认为它很有效,因为:

  • 您不必删除重复项。
  • 如果你有很多(重复的)特殊字符,它不会有任何影响

编辑(这里是示例代码)

    private static class SpecialChar implements Comparable<SpecialChar>{
        Integer position;
        char c;

        private SpecialChar(char c, Integer position) {
            this.c = c;
            this.position = position;
        }

        @Override
        public int compareTo(SpecialChar another) {
            return position.compareTo(another.position);
        }
    }

    public static void main(String[] args){
        String input = args[0];
        char[]  specialsChars = new char[]{'*','@','~','#'};
        List<SpecialChar> results = new ArrayList<SpecialChar>();
        for(char c:specialsChars){
            int position = input.indexOf(c);
            if(position>-1)results.add(new SpecialChar(c,position));
        }
        Collections.sort(results);
        StringBuilder builder = new StringBuilder();
        for(SpecialChar sp:results){
            builder.append(sp.c);
        }
        System.out.print(builder.toString());
   }
于 2013-02-01T11:36:45.413 回答
2

StringBuilder如果不存在,您可以使用 a 并将每个匹配的字符附加到它而不是使用字符串:-

StringBuilder builder = new StringBuilder();
while (m.find()) {
    String str = m.group();
    if (!builder.toString().contains(str)) {
        builder.append(str);
    }
}

// And finally
return builder.toString();

另一种方法是维护 a Set<String>,并继续向其中添加匹配的字符。它将自动删除重复项。然后您可以合并 的值Set以形成String使用Apache Commons StringUtils#join()的方法。或者您可以简单地迭代Set并将每个字符串附加到一个StringBuilder对象。你喜欢的任何方式都适合。

于 2013-02-01T11:26:28.207 回答
0

您需要捕获组。只需用括号将您的正则表达式括起来,然后为每个matcher#find获取它。它会是这样的:

public String detectAndGetSpecialCharacters(String text) {
    Pattern p = Pattern.compile("([~#@*])");
    Matcher m = pattern.matcher(text);
    Set<String> specialCharacters = new HashSet<String>();

    if (m.find()) {
        specialCharacters.add(m.group(1));
    }
    StringBuilder specialCharactersFound = new StringBuilder();

    for (String specialChar : specialCharacters) {
        specialCharactersFound.append(specialChar);
    }
    return specialCharactersFound.toString();
}

添加到Set将删除重复项,并在最后构建带有特殊字符的字符串。而且它不会返回null,这通常不是一件好事。


编辑

您实际上并不需要捕获组,因为您的正则表达式只获取特殊字符。你可以只使用Matcher#group. 但是,多学习一件事是件好事;)

于 2013-02-01T11:31:32.163 回答