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 の場合、特殊文字ごとにこのメソッドを呼び出します。これは、特殊文字が少なくとも 1 回存在することを意味します。

次に、見つかったインデックスに従って特殊文字を並べ替え、結果の文字列を作成します。

あまりエレガントではありませんが、次の理由から効率的だと思います。

  • 重複を削除する必要はありません。
  • 多くの(重複した)特殊文字がある場合、影響はありません

編集(サンプルコードはこちら)

    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、一致した各文字を追加することができます (まだ存在しない場合)。

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

// And finally
return builder.toString();

別の方法は、 を維持しSet<String>、一致する文字を追加し続けることです。重複を自動的に削除します。次に、の値をマージして、Apache Commonsメソッドを使用Setして形成できます。または、単純に を反復処理して、各文字列をオブジェクトに追加することもできます。どんな方法でも合います。String StringUtils#join()SetStringBuilder

于 2013-02-01T11:26:28.207 に答える
0

capture-groupが必要です。正規表現を括弧で囲み、それぞれ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。でも、もう1つ学ぶのは良いことです;)

于 2013-02-01T11:31:32.163 に答える