2016-07-06 12 views
1

Ich möchte nicht übereinstimmende Zeichenfolge, aber das Ergebnis null drucken.So drucken Sie nicht übereinstimmen Zeichenfolge

public class Replacement { 
    public static void main(String[] ignored) { 

     String str = "aaa bbb ddd"; 
     Map<String, String> mapping = new HashMap<>(); 
     mapping.put("aaa", "hello"); 
     mapping.put("bbb", "java"); 
     mapping.put("ccc", "world"); 

     Pattern pattern = Pattern.compile("([a-zA-Z_]+)"); // pattern compiling 
     Matcher matcher = pattern.matcher(str); // pattern matching 

     StringBuffer sb = new StringBuffer(); 
     while(matcher.find()) { // while matcher found 
     String replace = mapping.get(matcher.group()); 
     matcher.appendReplacement(sb, replace + " "); 
     } 
     matcher.appendTail(sb); 

     System.out.println(sb); 
    } 
} 

Das Ergebnis:

hallo java null // ich erwartet hatte „Hallo java dddd

Muss ich setzen while(!matcher.find())

+1

Da Sie auf Ihrer Karte nicht den Schlüssel 'dddd' haben, ist es richtig, ** null ** zurückzugeben. – developer033

Antwort

1

Um das zu erreichen, was Sie wollen, Sie müssen Sie überprüfen, ob ein Ersatz vorhanden ist oder nicht, wenn kein Ersatz vorhanden ist, müssen Sie den Schlüssel selbst anhängen

 String replace = mapping.get(matcher.group()); 
    if(replace==null) { 
     replace = matcher.group(); 
    } 
    matcher.appendReplacement(sb, replace + " "); 

hoffe das hilft.

1

Der folgende Code wurde auf IntelliJ 11 getestet und scheint ordnungsgemäß zu funktionieren. Ich denke, Ihre Absicht ist, jede Zeichenkette in der str Eingabe zusammenzubringen und sie möglicherweise zu ersetzen, wenn sie eine Zuordnung in der Hasenkarte hat. Das Problem besteht darin, dass Sie eine Ersetzung durchführen, ohne zu überprüfen, ob ein übereinstimmendes Wort in der Karte angezeigt wird. Ich fügte Logik hinzu, die bedingt einen Ersatz vornimmt, wenn eine Übereinstimmung eine Zuordnung hat.

public class Replacement { 
    public static void main(String[] ignored) { 

     String str = "aaa bbb ddd"; 
     Map<String, String> mapping = new HashMap<String, String>(); 
     mapping.put("aaa", "hello"); 
     mapping.put("bbb", "java"); 
     mapping.put("ccc", "world"); 

     Pattern pattern = Pattern.compile("([a-zA-Z_]+)");compiling 
     Matcher matcher = pattern.matcher(str); 

     StringBuffer sb = new StringBuffer(); 
     while(matcher.find()) { 
      String key = matcher.group();  // matched word is key into the map 
      String value = mapping.get(key); // attempt to get mapped word 
      if (value != null) {    // if mapping exists, 
       str = str.replace(key, value); // then make replacement 
      } 
     } 
     System.out.println(str); 
    } 
} 

Update:

Wenn Sie entlang der Linien von über Grenzfälle müssen sich Sorgen zu machen, was @ajb wies darauf hin, es wäre sicherer, nur durch Raum, um Ihre ursprüngliche Zeichenfolge zu teilen, ersetzen selektiv jedes Wort und dann rollt wieder nach oben in einen einzigen String zurück:

String[] parts = str.split(" "); 
String output = ""; 

for (int i=0; i < parts.length; ++i) { 
    String value = mapping.get(parts[i]); 
    if (value == null) { 
     value = parts[i]; 
    } 

    if (i > 0) { 
     output += " "; 
    } 
    output += value; 
} 
+0

Ich glaube nicht, dass Ihre neue Version das gleiche tut wie die Absicht des OP. Angenommen, die Eingabe ist "abbba bbb". 'abbba' passt nicht zu irgendetwas in der Map, also denke ich, dass es in der Saite bleiben sollte wie es ist, aber deine' str.replace() 'besiegt das. – ajb

+0

@ajb, Nein, das ist nicht korrekt. Mein Code _leaves_ irgendetwas in der Zeichenfolge, die nicht zugeordnet wird. Du hast den Code nicht sorgfältig gelesen, noch hast du ihn ausgeführt. –

+0

Ich habe es einfach ausgeführt, den Anfangswert von "str" ​​durch "abbba bbb" ersetzt und das überflüssige "Kompilieren" aus der Zeile entfernt, die "pattern" definiert. Das Ergebnis: '" ajavaa java "'. Das Ausführen des OP-Codes (Hinzufügen einer Überprüfung für 'replace! = Null ') führt zu" abbba java "'. Also ja, ich habe den Code sorgfältig gelesen. Und ich denke, letzteres ist das, wonach das OP sucht, obwohl meine Gedankenlesefähigkeiten suspekt sind. – ajb

1

Wenn es keine Übereinstimmung in der Karte ist, mapping.get()null in diesem Code zurückkehren würde:

 String replace = mapping.get(matcher.group()); 
    matcher.appendReplacement(sb, replace + " "); 

Ich bin mir nicht sicher, was Sie erwartet haben. Es scheint, als ob Sie dachten, dass, wenn die Zeichenfolge nicht in der Karte enthalten wäre, der Code magisch wissen würde, dass Sie die appendReplacement überspringen möchten. Aber natürlich kann Code keine Gedanken lesen und funktioniert nicht magisch. Wenn replacenull ist, würde das Programm trotzdem fortfahren und versuchen, die nächste Zeile auszuführen.

Das Ergebnis, das Sie sehen, liegt daran, wie der Operator + an Strings arbeitet; Wenn einer der Operanden null ist, dann fügt + tatsächlich die vierstellige Zeichenfolge "null" in das Ergebnis ein. So ist replace + " ""null ", und der Code ersetzt Ihre nicht übereinstimmende Zeichenfolge mit diesem. (Dies jedoch:

matcher.appendReplacement(sb, replace); 

hätte Ihnen eine NullPointerException gegeben.)

Also im Grunde, wollen Sie ihm sagen, nicht auf den Ersatz zu tun, wenn es keine Übereinstimmung gibt, und es gibt ein paar Möglichkeiten, dies zu tun:

String replace = mapping.get(matcher.group()); 
if (replace != null) { 
    matcher.appendReplacement(sb, replace + " "); 
} 

oder

if (mapping.containsKey(matcher.group())) { 
    String replace = mapping.get(matcher.group()); 
    matcher.appendReplacement(sb, replace + " "); 
} 

Wegen die Art und Weise appendReplacement funktioniert, wenn Sie es für eine matcher.find() überspringen, berührt es nicht matcher 's Position anhängen. Wenn also beim nächsten Mal durch die Schleife eine Übereinstimmung gefunden wird, wird die vorherige Übereinstimmung (die keine Zuordnung hatte) zu diesem Zeitpunkt kopiert. Oder, wenn wir aus der Schleife herausfallen, würde die vorherige Übereinstimmung durch appendTail kopiert werden.

Aber beachten Sie, dass der Code, den Sie geschrieben haben, extra Leerzeichen in das Ergebnis einfügt. Wenn es das ist, was Sie wollen, dann möchten Sie vielleicht den Ersatz reparieren, so dass es zusätzlichen Platz hinzufügt, auch wenn es keine Zuordnung gibt, anstatt es einfach in den nächsten append zu kopieren.

String replace = mapping.get(matcher.group()); 
if (replace == null) { 
    replace = matcher.group(); 
} 
matcher.appendReplacement(sb, replace + " "); 

die in der Tat würde "ddd" durch "ddd " in Ihrem Beispiel ersetzen. Sie müssen entscheiden, wie Sie mit den Leerzeichen umgehen möchten. Vielleicht wollten Sie wirklich keine zusätzlichen Räume? Denken Sie daran, dass die Methoden append Text von der Eingabe bis zu dem übereinstimmenden Punkt kopieren, einschließlich dieser Leerzeichen. Sie müssen also kein zusätzliches Leerzeichen einfügen, es sei denn, Sie möchten die Anzahl der Leerzeichen im Ergebnis wirklich erhöhen.

+0

Sie können sehen, aufgrund welcher Antwort wurde akzeptiert, dass die OP eine einfache Lösung, nicht unbedingt eine, die die Welt erobern kann. Ich freue mich darauf, wieder mit Ihnen auf SO zu interagieren. –

Verwandte Themen