5

現在、正規表現を使用して、codingbat.com の問題を解決しようとしています。

私はこれが初めてなので、段階的な説明をいただければ幸いです。これは String メソッドで比較的簡単に解決できましたが、正規表現を使用しようとしています。

プロンプトは次のとおりです。文字列と空でない単語文字列を指定すると、文字列内の単語が出現する直前と直後の各 char で構成される文字列を返します。単語の前後に char がない場合は無視してください。2 つの単語の間にある場合は、char が 2 回含まれている可能性があります。

wordEnds("abcXY123XYijk", "XY") → "c13i"
wordEnds("XY123XY", "XY") → "13"
wordEnds("XY1XY", "XY") → "11"

これまでの私のコード:

String regex = ".?" + word+ ".?";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);

String newStr = "";
while(m.find())
    newStr += m.group().replace(word, "");

return newStr;

問題は、単語の複数のインスタンスが連続して存在する場合、m.find() が単語を超えて進行するため、プログラムが単語の前の文字を見逃すことです。

例:wordEnds("abc1xyz1i1j", "1")を返す必要"cxziij"がありますが、私のメソッドは を返します"cxzij""i"

他の一般的な正規表現の問題に適用できる説明を含む、面倒ではない解決策をいただければ幸いです。

4

3 に答える 3

1

これはワンライナー ソリューションです。

String wordEnds = input.replaceAll(".*?(.)" + word + "(?:(?=(.)" + word + ")|(.).*?(?=$|." + word + "))", "$1$2$3");

これは、非キャプチャ グループ内の先読みとしてエッジ ケースに一致し、通常の (消費する) ケースに一致します。

あなたの要件は反復を必要としないことに注意してください.質問のタイトルだけが必要であると想定していますが、そうではありません.

絶対に安全にするために、特別な「正規表現」文字の場合に備えてすべての文字をエスケープする必要があることにも注意してくださいword。そのため、それを保証できない場合は、Pattern.quote(word)代わりにword.

これは、通常のケースとエッジ ケースのテストであり、動作することを示しています。

public static String wordEnds(String input, String word) {
    word = Pattern.quote(word); // add this line to be 100% safe
    return input.replaceAll(".*?(.)" + word + "(?:(?=(.)" + word + ")|(.).*?(?=$|." + word + "))", "$1$2$3");
}

public static void main(String[] args) {
    System.out.println(wordEnds("abcXY123XYijk", "XY"));
    System.out.println(wordEnds("abc1xyz1i1j", "1"));
}

出力:

c13i
cxziij
于 2012-11-03T19:38:57.423 に答える
0

次のように正規表現を使用します。

Matcher m = Pattern.compile("(.|)" + Pattern.quote(b) + "(?=(.?))").matcher(a);
for (int i = 1; m.find(); c += m.group(1) + m.group(2), i++);

このデモを確認してください。

于 2012-11-03T19:32:40.857 に答える
0

幅ゼロのアサーションである肯定的な後読みと肯定的な先読みを使用する

(?<=(.)|^)1(?=(.)|$)
    ^     ^     ^-looks for a character after 1 and captures it in group2
    |     |->matches 1..you can replace it with any word
    |
    |->looks for a character just before 1 and captures it in group 1..this is zero width assertion that doesn't move forward to match.it is just a test and thus allow us to capture the values

$1そしてあなたの価値を$2含んでいます..最後まで見つけ続けてください

したがって、これは次のようになります

String s1 = "abcXY123XYiXYjk";
String s2 = java.util.regex.Pattern.quote("XY");
String s3 = "";
String r = "(?<=(.)|^)"+s2+"(?=(.)|$)";
Pattern p = Pattern.compile(r);
Matcher m = p.matcher(s1);
while(m.find()) s3 += m.group(1)+m.group(2);
//s3 now contains c13iij

ここで働く

于 2012-11-03T19:19:40.847 に答える