0

Java には、文字列の一部/シーケンスを特定の新しいパターンに置き換える replace() および replaceAll() メソッドがあります。その機能の内部はどのように機能しますか? RegEx を使用せずに、文字列 OldPattern、NewPattern を入力し、OldPattern のすべての発生を NewPattern に再帰的に置き換える関数を作成する必要があるとしたらどうでしょうか。文字列入力の反復を使用して次のコードを実行しましたが、うまくいくようです。入力が文字列ではなく characterArray の場合はどうなるでしょうか?

  public String replaceOld(String aInput, String aOldPattern, String aNewPattern)
        {
             if ( aOldPattern.equals("") ) {
                throw new IllegalArgumentException("Old pattern must have content.");
             }

             final StringBuffer result = new StringBuffer();
             int startIdx = 0;
             int idxOld = 0;
             while ((idxOld = aInput.indexOf(aOldPattern, startIdx)) >= 0) {
               result.append( aInput.substring(startIdx, idxOld) );
               result.append( aNewPattern );

               //reset the startIdx to just after the current match, to see
               //if there are any further matches
               startIdx = idxOld + aOldPattern.length();
             }
             //the final chunk will go to the end of aInput
             result.append( aInput.substring(startIdx) );
             return result.toString();
          }
4

3 に答える 3

4

Javaには、文字列の一部/シーケンスを特定の新しいパターンに置き換えるためのreplace()メソッドとreplaceAll()メソッドがあります。

正確には、これらのメソッドは、関連する文字が置き換えられた新しい文字列を作成します。Java文字列は不変です。

その関数の内部はどのように機能しますか?

これは複雑すぎて、ここで詳細に説明することはできません。(そして、詳細は実際には実装ごとに異なる場合があります)。最善の策は、関連するライブラリクラスのソースコードを自分で読むことです。(ソースコードはJDKの一部として配布されており、Java IDEで表示できるはずです。または、Google検索でWeb上で検索されます。)

文字列OldPattern、NewPatternを入力し、RegExを使用せずにOldPatternのすべての出現箇所を再帰的にNewPatternに置き換える関数を作成する必要がある場合はどうなりますか?

Patternクラスを使用せずにパターンマッチ/置換を行うことについて話している場合は、そうです、それトリッキーです...それが無意味であることは言うまでもありません。

(再帰的な解決策は危険な場合があります。この問題を考慮してください:「「a」のすべてのインスタンスを「a」の「ba」に再帰的に置き換えます。結果はどうなりますか?これを実行しようとしてもよいですか?)


引数が単純な文字列(説明するパターンではない)であると仮定すると、再帰的な解決策があります(テストされていません)。

public String replace1(String in, String target, String replacement) {
    if (target.isEmpty()) {
        return in;
    }
    int pos = in.indexOf(target);
    if (pos < 0) {
        return in;
    }
    String updated = in.substring(0, pos) + replacement + 
                     in.substring(pos + target.length());
    return replace1(updated, target, replacement);
}

これにより、 1置換を再帰的にしたいバージョンの問題が解決されます。targetつまり、置換プロセスによって挿入されたインスタンスを置換する場合です。それをしたくない場合は、次のようにします。

public String replace2(String in, String target, String replacement) {
    if (target.isEmpty()) {
        return in;
    }
    int pos = in.indexOf(target);
    if (pos < 0) {
        return in;
    }
    return in.substring(0, pos) + replacement + 
                     replace2(in.substring(pos + target.length()),
                             target, replacement);
}

これらは、元の反復ソリューションよりも効率が低い可能性が高いことに注意してください。進行中の文字列コピーをすべて無視することさえあります。Javaは末尾呼び出しの最適化を行いません。


1-病理学的引数を使用して呼び出すreplace1と、スタックオーバーフローが発生します。例えばreplace1("ab", "b", "b")

于 2013-01-22T03:26:45.953 に答える
1

試す

public static String replaceOld(String aInput, String aOldPattern, String aNewPattern, int i) {
    i = aInput.indexOf(aOldPattern, i);
    if (i == -1) {
        return aInput;
    }
    aInput = aInput.substring(0, i) + aNewPattern + aInput.substring(i + aOldPattern.length());
    return replaceOld(aInput, aOldPattern, aNewPattern, i + aNewPattern.length());
}

iindexOf が毎回 pos 0 からスキャンしないように、param は最適化に使用されることに注意してください。また、「「a」の問題で「a」のすべてのインスタンスを「ba」に再帰的に置き換えることも解決します。

于 2013-01-22T05:27:21.100 に答える
0

たぶん、この方法はあなたの質問に答えます。

  static int indexOf(char[] string, char[] pattern, int startIndex) {
     int index = startIndex;
     while(true) {
         while(index < string.length && string[index] != pattern[0]) index++;
         if(index >= string.length || index+pattern.length > string.length) return -1;
         boolean match = true;
         for(int i = 1; i < pattern.length; i++) {
             if(string[index+i] != pattern[i]) {
                 match = false;
                 break;
             }
         }
         if(match) return index;
         else index += 1;
     }
  }

再帰的な置換方法が必要な場合は、これを使用します

static String replace(String string, String pattern, String replacement) {
  int index = string.indexOf(pattern);
  if(index < 0) return string;
  int endIndex = index+pattern.length();
  return string.substring(0, index) + replacement +
      replace(string.substring(endIndex), pattern, replacement);
}
于 2013-01-22T03:36:04.600 に答える