2010-11-17 13 views
6

Quindi supponiamo di avere:Come trovo i caratteri comuni a due stringhe in Java usando single replaceAll?

String s = "1479K"; 
String t = "459LP"; 

e voglio tornare

String commonChars = "49"; 

i caratteri comuni tra le due stringhe.

Ovviamente è possibile fare con un ciclo standard come:

String commonChars = ""; 
for (i = 0; i < s.length; i++) 
{ 
    char ch = s.charAt(i); 
    if (t.indexOf(ch) != -1) 
    { 
     commonChars = commonChars + ch; 
    } 
} 

Tuttavia vorrei essere in grado di fare questo in una linea utilizzando replaceAll. Questo può essere fatto nel modo seguente:

String commonChars = s.replaceAll("["+s.replaceAll("["+t+"]","")+"]",""); 

La mia domanda è: è possibile fare ciò utilizzando un unico invocazione di replaceAll? E quale sarebbe l'espressione regolare? Presumo di dover usare una specie di lookahead, ma il mio cervello diventa poltiglia quando ci penso.

risposta

4
String commonChars = s.replaceAll("[^"+t+"]",""); 

Nota che potrebbe essere necessario sfuggire ai caratteri speciali in t, ad es. utilizzando Pattern.quote(t) anziché t sopra.

+0

ora mi sento molto stupido – Kidburla

4

La risposta accettata:

String commonChars = s.replaceAll("[^"+t+"]",""); 

ha un bug !!!

Cosa succede se la stringa t ha un meta-carattere regex? In tal caso, replaceAll ha esito negativo.

See this program come un esempio in cui la stringa t ha ] in esso e ] è una meta-carattere regex che segna la fine della classe di caratteri. Chiaramente il programma non produce l'output atteso.

Perché?

considerare:

String s = "1479K"; 
String t = "459LP]"; 

Ora la regex diventerà (basta sostituire t):

String commonChars = s.replaceAll("[^459LP]]",""); 

che dice sostituire qualsiasi carattere diverso da 4, 5, 9, L, Pseguito da a] con niente. Che chiaramente non è quello che vuoi.

Per risolvere questi è necessario sfuggire allo ] in t. È possibile farlo manualmente come:

String t = "459LP\\]"; 

e il regex works fine.

Questo è un problema comune quando si usano espressioni regolari, quindi la classe java.util.regex.Pattern fornisce un metodo statico denominato quote che può essere usato per fare esattamente questo: citare le regex-metacaratteri in modo che essi sono trattati letteralmente.

Quindi, prima di utilizzare t in replaceAll citare come:

t = Pattern.quote(t); 

Program using quote method funziona come previsto.

+0

Questo significa che devo fare: commonChars String = s.replaceAll ("[^" + Pattern.quote (t) +" ]", ""); invece? Continuerà a controllare individualmente ciascun personaggio? – Kidburla

1
public class common { 

    public static void main(String args[]) { 
     String s = "FIRST"; 
     String s1 = "SECOND"; 
     String common = s.replaceAll("[^" + s1 + "]", ""); 
     System.out.println(common); 
    } 
} 
2

La risposta accettata non è corretta. Poiché lo replaceAll è un Pattern, è necessario considerare la sintassi. Cosa succederà se s1 = "\\t"? E cosa succederà se s1 = "]{"?

Se tutti i caratteri sono nell'intervallo [0 - 255], possiamo lavorare così:

  1. byte[] tmp = new byte[255];
  2. ciclo ciascun carattere nella prima stringa

    for (char c : str1.toCharArray())
    // or use charAt(i) here if (tmp[c] == 0) tmp[c] = 1;

  3. ciclo ogni carattere nella seconda stringa

    for (char c : str2.toCharArray()) if (tmp[c] == 1) tmp[c] = 2;

  4. loop the tmp array, trovare i membri con valore 2, l'indice è il carattere corretto che stiamo cercando.

Un'altra soluzione sta usando HashSet.retainAll(Collection<?> c);

Problemi correlati