2015-04-09 24 views
7

Ich gehe durch die Java CodingBat-Übungen. Here der ist ich gerade abgeschlossen hat:Regex zum Ersetzen bestimmter Zeichen vor und nach bestimmten Teilzeichenfolgen

einen String und eine nicht leere Wortkette gegeben, zurückgeben eine Zeichenfolge jeden Zeichen gemacht kurz vor und kurz nach jedem Auftreten des Wortes in der Zeichenkette. Ignoriere Fälle, in denen vor oder nach dem Wort kein Zeichen vorhanden ist, und ein Zeichen kann zweimal enthalten sein, wenn es zwischen zwei Wörtern liegt.

Mein Code, das funktioniert:

public String wordEnds(String str, String word){ 

    String s = ""; 
    String n = " " + str + " "; //To avoid OOB exceptions 

    int sL = str.length(); 
    int wL = word.length(); 
    int nL = n.length(); 

    int i = 1; 

    while (i < nL - 1) { 

     if (n.substring(i, i + wL).equals(word)) { 
      s += n.charAt(i - 1); 
      s += n.charAt(i + wL); 
      i += wL; 
     } else { 
      i++; 
     } 
    } 

    s = s.replaceAll("\\s", ""); 

    return s; 
} 

Meine Frage ist, über reguläre Ausdrücke. Ich möchte wissen, ob das oben genannte mit einer Regex-Anweisung machbar ist, und wenn ja, wie?

+0

Dieses Problem kann mit regulären Java-Ausdrücken schwierig zu lösen sein, da sich die Übereinstimmungen überlappen können, z. 'abcXY1XYijk' passt auf' XY' würde 'cXY1' und' 1XYi' als Gruppen haben. –

+0

Große Frage, übrigens^^ –

+0

fügen Sie einige Eingabe und erwartete Ausgabe – vks

Antwort

3

können Sie verwenden Java Regex-Objekte Pattern und Matcher, dies zu tun.

public class CharBeforeAndAfterSubstring { 
    public static String wordEnds(String str, String word) { 
     java.util.regex.Pattern p = java.util.regex.Pattern.compile(word); 
     java.util.regex.Matcher m = p.matcher(str); 
     StringBuilder beforeAfter = new StringBuilder(); 

     for (int startIndex = 0; m.find(startIndex); startIndex = m.start() + 1) { 
      if (m.start() - 1 > -1) 
       beforeAfter.append(Character.toChars(str.codePointAt(m.start() - 1))); 
      if (m.end() < str.length()) 
       beforeAfter.append(Character.toChars(str.codePointAt(m.end()))); 
     } 

     return beforeAfter.toString(); 
    } 
    public static void main(String[] args) { 
     String x = "abcXY1XYijk"; 
     String y = "XY"; 
     System.out.println(wordEnds(x, y)); 

    } 
} 
+0

Ich schätze den 'kann sein' Teil o die Frage ist mehrdeutig. In diesem Fall, es _should_ sollte enthalten sein, oder der Test ist fehlgeschlagen – alanbuchanan

+0

@alanbuchanan Bearbeitete die Antwort, bitte auschecken. Ein wenig mehr Indexierungslogik wird hinzugefügt, um sicherzustellen, dass Überlappungen korrekt berücksichtigt werden. –

+0

Das wird nicht mit 16/17 Ebenen von Unicode funktionieren.Bitte hör auf 'charAt' zu verwenden: es ist nicht für den Zweck geeignet. – tchrist

1

Um einen String zu bekommen das Zeichen vor und nach jedem Auftreten einer Zeichenfolge in den andere enthalten, können Sie den regulären Ausdruck verwenden:

"(^|.)" + str + "(.|$)" 

und dann könnte man die Gruppen durchlaufen und sie verketten.

wird Dieser Ausdruck sucht (^|.), entweder den Beginn der Zeichenfolge ^ oder ein beliebiges Zeichen ., von str Wert, gefolgt von (.|$) gefolgt, jedes Zeichen . oder das Ende der Zeichenfolge $.

Man könnte so etwas wie dies versuchen:

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public String wordEnds(String str, String word){ 
    Pattern p = Pattern.compile("(.)" + str + "(.)"); 
    Matcher m = p.matcher(word); 
    String result = ""; 
    int i = 0; 
    while(m.find()) { 
     result += m.group(i++); 
    } 
    return result; 
} 
+0

Wie macht es 'eine Zeichenfolge aus jedem Zeichen direkt vor und kurz nach jedem Auftreten des Wortes in der Zeichenfolge zurückgeben? –

+0

@Scary Wombat Danke für die Rückmeldung. Du hast recht. Ich habe ersetzt, anstatt nur diese Charaktere zurückzugeben, das Gegenteil von dem, was gefragt wurde. Die Antwort wurde aktualisiert. –

+0

Ihr Code schlägt die meisten Tests bei http://codingbat.com/prob/p147538 fehl, von denen das OP versucht zu lernen. – user883499

1
(?=(.|^)XY(.|$)) 

this.Just greifen die Captures Versuchen und die None oder empty values.See Demo entfernen.

https://regex101.com/r/sJ9gM7/73

+0

Dies berücksichtigt nicht die Tatsache, dass 'XY' etwas anderes sein könnte, wie von' str' in der Frage definiert – alanbuchanan

Verwandte Themen