Extraer dígitos de una cadena en Java

207

Tengo un Stringobjeto Java Necesito extraer solo dígitos de él. Daré un ejemplo:

"123-456-789" quiero "123456789"

¿Existe una función de biblioteca que extrae solo dígitos?

Gracias por las respuestas Antes de probar esto, ¿debo saber si tengo que instalar alguna biblioteca adicional?

usuario488469
fuente

Respuestas:

546

Puede usar expresiones regulares y eliminar no dígitos.

str = str.replaceAll("\\D+","");
codictorio
fuente
66
Buen código corto. Una búsqueda lineal podría ser más rápida, pero creo que la tuya tiene más sentido.
Kasten
18
Supongo que puedes votar en contra de todo lo que quieras (sin sarcasmo) Pero mi opinión personal es: cuando grandes desarrolladores (y tenemos muchos de ellos aquí) comparten algunos de sus consejos de forma gratuita, entonces voy a honrar eso, y solo rechazo cosas que son realmente horribles (revisa mi perfil, mi actual relación es 14xx arriba contra 17 abajo). Pero esa es mi filosofía personal y eres libre de tener la tuya.
Sean Patrick Floyd
78
Esto no funcionará si su número tiene un punto decimal, también elimina el punto decimal. str = str.replaceAll("[^\\.0123456789]","");
Aravindan R
2
Aunque la expresión regular es extremadamente simple y limpia a la vista, adolece de problemas de rendimiento y solo debe usarse donde tiene una tira única (como un formulario enviado). Si está procesando muchos datos, este no es el camino a seguir.
Brill Pappin
2
y si es necesario para excluir cualquier cosa, como un punto decimal,(?!\\.)
azerafati
49

Aquí hay una solución más detallada. Menos elegante, pero probablemente más rápido:

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();
}

Código de prueba:

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);
}

Salida:

0123456789

Por cierto: no utilicé Character.isDigit (ch) porque acepta muchos otros caracteres, excepto 0 - 9.

Sean Patrick Floyd
fuente
44
Debe proporcionar un tamaño al StringBuilderconstructor (como input.length()) para asegurarse de que no sea necesario reasignarlo. No necesita exigir un Stringaquí; CharSequencees suficiente Además, puede separar la asignación de la StringBuildercolección de no dígitos escribiendo una función separada que acepte una CharSequenceentrada y una Appendableinstancia como un acumulador de salida.
seh
1
@seh Suena interesante, pero en lugar de comentar, ¿por qué no crear su propia respuesta con las extensiones?
RedYeti
3
@RedYeti Dejar que esta respuesta permanezca y agregar un comentario es más honorable ya que Sean recibe votos a favor en ese momento. También es mucho más rápido criticar el código de otros que reescribirlo si tiene prisa. No castigue a Seh por hacer una contribución valiosa, no tuvo que agregar esos útiles datos, y su respuesta hace que sea menos probable que lo haga la próxima vez.
KomodoDave
2
No estoy "castigando" a nadie, eso es una completa mala interpretación de lo que le estaba diciendo a @seh. Mi punto fue que sus comentarios agregaron tanto que valió la pena y de hecho cambiaron tanto que sentí que merecía una respuesta propia. Estoy seguro de que a Sean Patrick Floyd no le preocupa que las felicitaciones solo ayuden a los demás y que estaría perfectamente contento de que él les brinde su propia respuesta. Simplemente estaba alentando a Seh ya que sentía que su contribución merecía una mayor visibilidad. Cómo es posible leer mi comentario como cualquier otra cosa me desconcierta por completo, pero me disculpo si lo hizo de alguna manera.
RedYeti
1
Me gusta cómo se reanudan estas discusiones después de permanecer latentes por un tiempo. Quizás lo mejor que puedo hacer aquí es editar la respuesta de Sean y aumentarla con mis sugerencias. De esa manera, Sean continuará recibiendo el crédito a menos que la respuesta pase al estado wiki de la comunidad.
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
fuente
Pensé en usar Character.isDigit (), pero también acepta algunos caracteres que no son 0-9 (ver documentos: download.oracle.com/javase/6/docs/api/java/lang/… )
Sean Patrick Floyd
21

Usando Google Guava:

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

ACTUALIZAR:

El uso de CharMatcher precalculado puede mejorar aún más el rendimiento

CharMatcher ASCII_DIGITS=CharMatcher.inRange('0','9').precomputed();  
ASCII_DIGITS.retainFrom("123-456-789");
Emil
fuente
3
Ahora hay Charmatcher.DIGITpredefinido.
Duncan McGregor
15
input.replaceAll("[^0-9?!\\.]","")

Esto ignorará los puntos decimales.

por ejemplo: si tiene una entrada como 445.3kgserá la salida 445.3.

usuario3679646
fuente
Tengo "4.5 zi". no funciona porque mantiene el segundo. también
Marian Klühspies
11

Usando Google Guava:

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

CharMatcher es conectable y bastante interesante de usar, por ejemplo, puede hacer lo siguiente:

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

salida == 123-456-789

BjornS
fuente
Muy buena solución (+1), pero tiene el mismo problema que otros: muchos caracteres califican como dígitos unicode, no solo los dígitos ascii. Este código retendrá todos estos caracteres: unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D
Sean Patrick Floyd
@seanizer: Entonces será mejor CharMatcher.inRange ('1', '9'). retiene ((123-456-789 ")
Emil
@Emil se parece más a CharMatcher.inRange ('0', '9'), pero sí
Sean Patrick Floyd el
inRange es lo que hay detrás de CharMatcher.DIGIT; pastie.org/1252471 Simplemente tiene en cuenta los rangos de números UTF especiales, todavía los consideraría como dígitos, ya que en realidad lo son, simplemente no están codificados en ASCII.
BjornS
También puede usar CharMatcher.JAVA_DIGIT para el mismo propósito, que solo aceptará dígitos según Character.isDigit
BjornS
6

Use expresiones regulares para cumplir con sus requisitos.

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
fuente
5

Me inspiré en el código Sean Patrick Floyd y lo reescribí poco para obtener el máximo rendimiento que obtengo.

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 );
}

Hago una prueba de rendimiento a una cadena muy larga con números mínimos y el resultado es:

  • El código original es un 25,5% más lento
  • El enfoque de la guayaba es 2.5-3 veces más lento
  • La expresión regular con D + es 3-3.5 veces más lenta
  • La expresión regular con solo D es 25 veces más lenta

Por cierto, depende de la longitud de esa cadena. Con una cuerda que contiene solo 6 números, la guayaba es 50% más lenta y la expresión regular 1 veces más lenta

Perlos
fuente
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);          
   }
}

Salida: 11

ruchin khare
fuente
3

Puedes usar str.replaceAll("[^0-9]", "");

sendon1982
fuente
2

He finalizado el código para los números de teléfono +9 (987) 124124.

Los caracteres Unicode ocupan 4 bytes.

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
fuente
2

Código:

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
fuente
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
fuente