2010-11-17 18 views
6

suppose que oui je:Comment puis-je trouver les caractères communs à deux chaînes en Java en utilisant single replaceAll?

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

et je veux revenir

String commonChars = "49"; 

les caractères communs entre les deux chaînes.

De toute évidence, il est possible de faire avec une boucle standard comme:

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

Cependant, je voudrais être en mesure de le faire en une seule ligne à l'aide replaceAll. Cela peut se faire comme suit:

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

Ma question est: est-il possible de le faire en utilisant un seul invocation de replaceAll? Et quelle serait l'expression régulière? Je suppose que je dois utiliser une sorte de lookahead, mais mon cerveau se transforme en bouillie quand j'y pense.

Répondre

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

Notez que vous devrez peut-être extraire des caractères spéciaux dans t, par ex. en utilisant Pattern.quote(t) au lieu de t ci-dessus.

+0

maintenant je me sens très stupide – Kidburla

4

La réponse acceptée:

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

a un bug !!! Que se passe-t-il si la chaîne t a un méta-caractère regex? Dans ce cas, le replaceAll échoue.

See this program comme un exemple dans lequel la chaîne a t] en elle et ] est un méta-caractère regex qui marque la fin de la classe de caractères. Clairement, le programme ne produit pas la sortie attendue.

Pourquoi?

Tenir compte:

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

Maintenant, le regex deviendra (Il suffit de remplacer t):

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

Ce qui dit remplacer tout autre caractère que 4, 5, 9, L, Psuivie] avec rien. Ce qui n'est clairement pas ce que vous voulez.

Pour les réparer, vous devez sortir le ] en t. Vous pouvez le faire manuellement:

String t = "459LP\\]"; 

et regex works fine.

Ceci est un problème commun lors de l'utilisation regex, de sorte que la classe java.util.regex.Pattern fournit une méthode statique nommée quote qui peut être utilisé pour faire exactement cela: citer les regex métacaractères afin qu'ils soient traités littéralement.

Alors avant d'utiliser t en replaceAll vous citer comme:

t = Pattern.quote(t); 

Program using quote method fonctionne comme prévu.

+0

Est-ce que cela veut dire que je dois faire: chaîne commonChars = s.replaceAll ("[^" + Pattern.quote (t) + » ] "," "); à la place? Est-ce que cela vérifie toujours chaque personnage individuellement? – 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 réponse acceptée est incorrecte. Parce que le replaceAll est un motif, nous devons considérer la syntaxe. Que se passera-t-il si s1 = "\\t"? Et que se passera-t-il si s1 = "]{"?

Si tous les caractères sont dans la plage [0 - 255], nous pouvons travailler comme ceci:

  1. byte[] tmp = new byte[255];
  2. boucle

    chaque char dans la première chaîne

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

  3. boucle

    chaque caractère en seconde chaîne

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

  4. boucle le tableau tmp, trouver les membres avec la valeur de 2, l'index est le bon char que nous recherchons.

Une autre solution utilise HashSet.retainAll(Collection<?> c);