2011-10-05 18 views
8

テキストを含むファイルがあります。 "substr1"、 "substr2"、 "substr3"などの部分文字列があります。私はそれらの部分文字列をすべて "repl1"、 "repl2"、 "repl3"のような他のテキストに置き換える必要があります。その後、re.sub機能に置き換え、|「」複数の部分文字列を一度に置換する

{ 
"substr1": "repl1", 
"substr2": "repl2", 
"substr3": "repl3" 
} 

とでキーを結ぶパターンを作成します:Pythonでは、私はこのような辞書を作成します。 Javaでこれと同様の簡単な方法がありますか?

+0

関連スレッド - http://stackoverflow.com/questions/2049528/java-best-way-for-string-find-and-replace – adatapost

答えて

14

これはあなたのPythonの提案は、Javaに変換する方法である:

Map<String, String> replacements = new HashMap<String, String>() {{ 
    put("substr1", "repl1"); 
    put("substr2", "repl2"); 
    put("substr3", "repl3"); 
}}; 

String input = "lorem substr1 ipsum substr2 dolor substr3 amet"; 

// create the pattern joining the keys with '|' 
String regexp = "substr1|substr2|substr3"; 

StringBuffer sb = new StringBuffer(); 
Pattern p = Pattern.compile(regexp); 
Matcher m = p.matcher(input); 

while (m.find()) 
    m.appendReplacement(sb, replacements.get(m.group())); 
m.appendTail(sb); 


System.out.println(sb.toString()); // lorem repl1 ipsum repl2 dolor repl3 amet 

このアプローチは、simultanious(すなわち、 "一度に")の交換を行います。あなたは

"a" -> "b" 
"b" -> "c" 

を持つことが起こった場合は、"c c"を与えるだろうreplaceまたはreplaceAllにチェーンいくつかのコールがすべき示唆答えとは対照的に、すなわち、このアプローチは、"a b" -> "b c"を与えるだろう。


(あなたがプログラム的に正規表現を作成するには、このアプローチを一般化した場合、確認してくださいあなたPattern.quote個々の検索語とMatcher.quoteReplacement各代替語。)

+0

このアプローチとStringUtils.replaceEachとの違いは?またはreplaceEachはreplaceAllと同じですか? –

+0

このアプローチは、任意の置換関数を提供できるのでより一般的です( 'm.appendReplacement'行を見てください)。第2に、文字列操作ルーチンのためにサードパーティのライブラリを含める必要はありません。 (既にApache Commonsに依存している場合や別の依存関係を全く気にしない場合は、 'replaceEach'アプローチをとってください) – aioobe

+0

(いいえ、' replaceEach'は 'replaceAll'と同じではありません。 – aioobe

2
yourString.replace("substr1", "repl1") 
      .replace("substr2", "repl2") 
      .replace("substr3", "repl3"); 
+4

+1 ...それは一瞬ではありません。例が異なる場合は、「a」 - >「b」と「b」 - >「c」と言うと、結果に「a」があっても「b」はありません入力に – aioobe

+0

かなり醜いですが、とにかく感謝します:) –

+0

@aioobe: 'StringUtils.replaceEach()'はこれをうまく処理します。 – palacsint

-1
return yourString.replaceAll("substr1","relp1"). 
        replaceAll("substr2","relp2"). 
        replaceAll("substr3","relp3") 
+0

-1。これは一度にすべてではなく、不必要にプレーンなStringメソッド(replace)の代わりにregexメソッド(replaceAll)を使用します。 – Boann

1

まず、問題のデモ:

String s = "I have three cats and two dogs."; 
s = s.replace("cats", "dogs") 
    .replace("dogs", "budgies"); 
System.out.println(s); 

これは、cats => dogsおよびdogs => budgiesを置き換えることを目的としていますが、順次置換は以前のr不都合な出力は次のとおりです。

私には3つのbudgiesと2つのbudgiesがあります。

これは私の同時置換方法の実装です。それはString.regionMatchesを使用して書くことは簡単です:

public static String simultaneousReplace(String subject, String... pairs) { 
    if (pairs.length % 2 != 0) throw new IllegalArgumentException(
     "Strings to find and replace are not paired."); 
    StringBuilder sb = new StringBuilder(); 
    int numPairs = pairs.length/2; 
    outer: 
    for (int i = 0; i < subject.length(); i++) { 
     for (int j = 0; j < numPairs; j++) { 
      String find = pairs[j * 2]; 
      if (subject.regionMatches(i, find, 0, find.length())) { 
       sb.append(pairs[j * 2 + 1]); 
       i += find.length() - 1; 
       continue outer; 
      } 
     } 
     sb.append(subject.charAt(i)); 
    } 
    return sb.toString(); 
} 

テスト:

String s = "I have three cats and two dogs."; 
s = simultaneousReplace(s, 
    "cats", "dogs", 
    "dogs", "budgies"); 
System.out.println(s); 

出力:

私は3匹の犬と2匹のセキセイインコを持っています。

さらに、最も長いマッチを探すために、同時に交換するときに便利なことがあります。 (例えば、PHPのstrtr関数はこれを行います。)これは私の実装です:

public static String simultaneousReplaceLongest(String subject, String... pairs) { 
    if (pairs.length % 2 != 0) throw new IllegalArgumentException(
     "Strings to find and replace are not paired."); 
    StringBuilder sb = new StringBuilder(); 
    int numPairs = pairs.length/2; 
    for (int i = 0; i < subject.length(); i++) { 
     int longestMatchIndex = -1; 
     int longestMatchLength = -1; 
     for (int j = 0; j < numPairs; j++) { 
      String find = pairs[j * 2]; 
      if (subject.regionMatches(i, find, 0, find.length())) { 
       if (find.length() > longestMatchLength) { 
        longestMatchIndex = j; 
        longestMatchLength = find.length(); 
       } 
      } 
     } 
     if (longestMatchIndex >= 0) { 
      sb.append(pairs[longestMatchIndex * 2 + 1]); 
      i += longestMatchLength - 1; 
     } else { 
      sb.append(subject.charAt(i)); 
     } 
    } 
    return sb.toString(); 
} 

なぜこれが必要ですか?例は次のとおりです。

String truth = "Java is to JavaScript"; 
truth += " as " + simultaneousReplaceLongest(truth, 
    "Java", "Ham", 
    "JavaScript", "Hamster"); 
System.out.println(truth); 

出力:

をハムたちはsimultaneousReplace代わりのsimultaneousReplaceLongestを使用していた場合、出力は "HamScript" を持っているだろうハムスター

にそのままJavaはJavaScriptにあります「ハムスター」の代わりに:

上記の方法では大文字と小文字が区別されます。大文字小文字を区別しないバージョンが必要な場合は、String.regionMatchesignoreCaseパラメータを取ることができるため、上記を変更するのは簡単です。

関連する問題