Extraire les chiffres d'une chaîne en Java

207

J'ai un Stringobjet Java . Je n'ai besoin d'en extraire que des chiffres. Je vais donner un exemple:

"123-456-789" Je voudrais "123456789"

Existe-t-il une fonction de bibliothèque qui extrait uniquement les chiffres?

Merci pour les réponses. Avant de les essayer, je dois savoir si je dois installer des bibliothèques supplémentaires?

user488469
la source

Réponses:

546

Vous pouvez utiliser l'expression régulière et supprimer les non-chiffres.

str = str.replaceAll("\\D+","");
codaddict
la source
6
joli code court. Une recherche linéaire pourrait être plus rapide mais je pense que la vôtre est plus logique.
kasten
18
Je suppose que vous pouvez downvote tout ce que vous aimez downvote (aucun sarcasme prévu). Mais mon opinion personnelle est la suivante: lorsque de grands développeurs (et nous en avons beaucoup ici) partagent gratuitement certains de leurs conseils, alors je vais honorer cela, et je ne vote que des trucs vraiment horribles (vérifiez mon profil, mon actuel est 14xx contre 17 vers le bas). Mais c'est ma philosophie personnelle et vous êtes libre d'avoir la vôtre.
Sean Patrick Floyd
78
Cela ne fonctionnera pas si votre numéro a un point décimal, il supprime également le point décimal. str = str.replaceAll("[^\\.0123456789]","");
Aravindan R
2
Bien que l'expression régulière soit extrêmement simple et propre à regarder, elle souffre de problèmes de performances et ne doit être utilisée que lorsque vous avez une bande unique (comme un formulaire soumis). Si vous traitez beaucoup de données, ce n'est pas la voie à suivre.
Brill Pappin
2
et si vous devez exclure quoi que ce soit, comme un point décimal,(?!\\.)
azerafati
49

Voici une solution plus détaillée. Moins élégant, mais probablement plus rapide:

public static String stripNonDigits(
            final CharSequence input /* inspired by seh's comment */){
    final StringBuilder sb = new StringBuilder(
            input.length() /* also inspired by seh's comment */);
    for(int i = 0; i < input.length(); i++){
        final char c = input.charAt(i);
        if(c > 47 && c < 58){
            sb.append(c);
        }
    }
    return sb.toString();
}

Code de test:

public static void main(final String[] args){
    final String input = "0-123-abc-456-xyz-789";
    final String result = stripNonDigits(input);
    System.out.println(result);
}

Production:

0123456789

BTW: Je n'ai pas utilisé Character.isDigit (ch) car il accepte de nombreux autres caractères sauf 0 - 9.

Sean Patrick Floyd
la source
4
Vous devez fournir une taille au StringBuilderconstructeur (tel que input.length()) pour vous assurer qu'il n'aura pas besoin d'être réaffecté. Vous n'avez pas besoin d'exiger un Stringici; CharSequencesuffit. En outre, vous pouvez séparer l'allocation de la StringBuilderde la collection de non-chiffres en écrivant une fonction distincte qui accepte un CharSequencecomme entrée et une Appendableinstance comme un accumulateur de sortie.
seh
1
@seh Cela semble intéressant mais plutôt que de commenter pourquoi ne pas créer votre propre réponse avec les extensions?
RedYeti
3
@RedYeti Laisser cette réponse et ajouter un commentaire est plus honorable puisque Sean reçoit alors des votes positifs. Il est également beaucoup plus rapide de critiquer le code des autres que de le réécrire si vous êtes pressé. Ne punissez pas seh pour avoir apporté une contribution précieuse, il n'a pas eu à ajouter ces friandises utiles, et votre réponse le rend moins susceptible de le faire la prochaine fois.
KomodoDave
2
Je ne «punis» personne - c'est une interprétation complètement erronée de ce que je disais à @seh. Je voulais dire que ses commentaires ont ajouté tellement de choses qui valaient la peine et ont en fait tellement changé que j'estimais que cela méritait une réponse qui lui était propre. Je suis sûr que Sean Patrick Floyd ne se soucie pas que les compliments aident uniquement les autres et serait parfaitement heureux de seh apporter sa propre réponse. J'encourageais simplement seh car je sentais que sa contribution méritait une plus grande visibilité. Comment il est possible de lire mon commentaire comme quoi que ce soit d'autre me laisse complètement perplexe, mais je m'excuse de voir si c'est le cas.
RedYeti
1
J'aime la façon dont ces discussions reprennent après avoir dormi pendant un certain temps. La meilleure chose à faire ici est peut-être pour moi de modifier la réponse de Sean, en l'augmentant avec mes suggestions. De cette façon, Sean continuera à recevoir le crédit à moins que la réponse ne passe au statut de wiki communautaire.
seh
22
public String extractDigits(String src) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < src.length(); i++) {
        char c = src.charAt(i);
        if (Character.isDigit(c)) {
            builder.append(c);
        }
    }
    return builder.toString();
}
dogbane
la source
J'ai pensé à utiliser Character.isDigit () moi-même, mais il accepte également certains caractères qui ne sont pas 0-9 (voir les documents: download.oracle.com/javase/6/docs/api/java/lang/… )
Sean Patrick Floyd
21

Utilisation de Google Guava:

CharMatcher.inRange('0','9').retainFrom("123-456-789")

METTRE À JOUR:

L'utilisation de CharMatcher précalculé peut encore améliorer les performances

CharMatcher ASCII_DIGITS=CharMatcher.inRange('0','9').precomputed();  
ASCII_DIGITS.retainFrom("123-456-789");
Emil
la source
3
Il est désormais Charmatcher.DIGITprédéfini.
Duncan McGregor
15
input.replaceAll("[^0-9?!\\.]","")

Cela ignorera les décimales.

par exemple: si vous avez une entrée comme 445.3kgla sortie sera 445.3.

user3679646
la source
J'ai "4.5 zi". ne fonctionne pas car il garde le second. aussi
Marian Klühspies
11

Utilisation de Google Guava:

CharMatcher.DIGIT.retainFrom("123-456-789");

CharMatcher est enfichable et très intéressant à utiliser, par exemple, vous pouvez faire ce qui suit:

String input = "My phone number is 123-456-789!";
String output = CharMatcher.is('-').or(CharMatcher.DIGIT).retainFrom(input);

sortie == 123-456-789

BjornS
la source
Très belle solution (+1), mais elle souffre du même problème que les autres: beaucoup de caractères sont qualifiés de chiffres unicode, pas seulement les chiffres ascii. Ce code conservera tous ces caractères: unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D
Sean Patrick Floyd
@seanizer: Alors ce sera mieux CharMatcher.inRange ('1', '9'). retenueFrom ("123-456-789")
Emil
@Emil ressemble plus à CharMatcher.inRange ('0', '9'), mais: oui
Sean Patrick Floyd
inRange est ce qui se cache derrière CharMatcher.DIGIT; pastie.org/1252471 Il prend simplement en compte les plages de numéros UTF supplémentaires, je les considérerais toujours comme des chiffres, car en réalité ils le sont, ils ne sont tout simplement pas encodés en ASCII.
BjornS
Vous pouvez également utiliser CharMatcher.JAVA_DIGIT dans le même but, qui n'acceptera que les chiffres selon Character.isDigit
BjornS
6

Utilisez une expression régulière pour correspondre à vos besoins.

String num,num1,num2;
String str = "123-456-789";
String regex ="(\\d+)";
Matcher matcher = Pattern.compile( regex ).matcher( str);
while (matcher.find( ))
{
num = matcher.group();     
System.out.print(num);                 
}
Raghunandan
la source
5

Je me suis inspiré du code Sean Patrick Floyd et je l'ai peu réécrit pour des performances maximales.

public static String stripNonDigitsV2( CharSequence input ) {
    if (input == null)
        return null;
    if ( input.length() == 0 )
        return "";

    char[] result = new char[input.length()];
    int cursor = 0;
    CharBuffer buffer = CharBuffer.wrap( input );

    while ( buffer.hasRemaining() ) {
        char chr = buffer.get();
        if ( chr > 47 && chr < 58 )
            result[cursor++] = chr;
    }

    return new String( result, 0, cursor );
}

Je fais un test de performance sur une chaîne très longue avec un nombre minimal et le résultat est:

  • Le code d'origine est 25,5% plus lent
  • L'approche de la goyave est 2,5 à 3 fois plus lente
  • L'expression régulière avec D + est 3-3,5 fois plus lente
  • L'expression régulière avec seulement D est plus de 25 fois plus lente

Btw cela dépend de la longueur de cette chaîne. Avec une chaîne qui ne contient que 6 chiffres, la goyave est 50% plus lente et regexp 1 fois plus lente

Perlos
la source
5
public class FindDigitFromString 
{

    public static void main(String[] args) 
    {
        String s="  Hi How Are You 11  ";        
        String s1=s.replaceAll("[^0-9]+", "");
        //*replacing all the value of string except digit by using "[^0-9]+" regex.*
       System.out.println(s1);          
   }
}

Sortie: 11

ruchin khare
la source
3

Vous pouvez utiliser str.replaceAll("[^0-9]", "");

sendon1982
la source
2

J'ai finalisé le code pour les numéros de téléphone +9 (987) 124124.

Les caractères Unicode occupent 4 octets.

public static String stripNonDigitsV2( CharSequence input ) {
    if (input == null)
        return null;
    if ( input.length() == 0 )
        return "";

    char[] result = new char[input.length()];
    int cursor = 0;
    CharBuffer buffer = CharBuffer.wrap( input );
    int i=0;
    while ( i< buffer.length()  ) { //buffer.hasRemaining()
        char chr = buffer.get(i);
        if (chr=='u'){
            i=i+5;
            chr=buffer.get(i);
        }

        if ( chr > 39 && chr < 58 )
            result[cursor++] = chr;
        i=i+1;
    }

    return new String( result, 0, cursor );
}
Kairat Koibagarov
la source
2

Code:

public class saasa {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String t="123-456-789";
        t=t.replaceAll("-", "");
        System.out.println(t);
    }
nagalakshmi kotha
la source
0
import java.util.*;
public class FindDigits{

 public static void main(String []args){
    FindDigits h=new  FindDigits();
    h.checkStringIsNumerical();
 }

 void checkStringIsNumerical(){
    String h="hello 123 for the rest of the 98475wt355";
     for(int i=0;i<h.length();i++)  {
      if(h.charAt(i)!=' '){
       System.out.println("Is this '"+h.charAt(i)+"' is a digit?:"+Character.isDigit(h.charAt(i)));
       }
    }
 }

void checkStringIsNumerical2(){
    String h="hello 123 for 2the rest of the 98475wt355";
     for(int i=0;i<h.length();i++)  {
         char chr=h.charAt(i);
      if(chr!=' '){
       if(Character.isDigit(chr)){
          System.out.print(chr) ;
       }
       }
    }
 }
}
sarkar vijay
la source