Extrair dígitos de uma sequência em Java


207

Eu tenho um Stringobjeto Java . Eu preciso extrair apenas dígitos dele. Vou dar um exemplo:

"123-456-789" eu quero "123456789"

Existe uma função de biblioteca que extrai apenas dígitos?

Obrigado pelas respostas. Antes de experimentar, preciso saber se tenho que instalar alguma biblioteca adicional?

Respostas:


546

Você pode usar regex e excluir não dígitos.

str = str.replaceAll("\\D+","");

6
bom código curto. Uma pesquisa linear pode ser mais rápida, mas acho que a sua faz mais sentido.
— Kasten

18
Eu acho que você pode diminuir o voto de qualquer coisa que você gostaria de votar (sem intenção de sarcasmo). Mas minha opinião pessoal é: quando grandes desenvolvedores (e temos muitos deles aqui) compartilharem alguns de seus conselhos de graça, então eu irei honrá-lo, e eu apenas desisto de coisas realmente terríveis (veja meu perfil, meu perfil atual). a relação é 14xx acima contra 17 abaixo). Mas essa é a minha filosofia pessoal e você é livre para ter a sua.
— Sean Patrick Floyd

78
Isso não funcionará se o seu número tiver um ponto decimal, ele também removerá o ponto decimal. str = str.replaceAll("[^\\.0123456789]","");
— Aravindan R

2
Embora o regex seja extremamente simples e limpo de analisar, ele sofre de problemas de desempenho e só deve ser usado onde você tem uma faixa única (como um envio de formulário). Se você estiver processando muitos dados, esse não é o caminho a seguir.
— Brill Pappin

2
e se você precisar excluir qualquer coisa, como um ponto decimal,(?!\\.)
— azerafati

49

Aqui está uma solução mais detalhada. Menos elegante, mas provavelmente mais 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 do teste:

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

Resultado:

0123456789

BTW: Eu não usei Character.isDigit (ch) porque ele aceita muitos outros caracteres, exceto 0 - 9.


4
Você deve fornecer um tamanho ao StringBuilderconstrutor (como input.length()) para garantir que ele não precise ser realocado. Você não precisa exigir um Stringaqui; CharSequenceé suficiente. Além disso, você pode separar a alocação do StringBuilderda coleção de não dígitos, escrevendo uma função separada que aceite a CharSequencecomo entrada e uma Appendableinstância como um acumulador de saída.
— seh

1
@seh Parece interessante, mas em vez de comentar, por que não criar sua própria resposta com as extensões?
— RedYeti

3
@RedYeti Deixar esta resposta permanecer e adicionar um comentário é mais honroso, já que Sean recebe votos positivos. Também é muito mais rápido criticar o código de outras pessoas do que reescrevê-lo se você estiver com pressa. Não castigue seh por dar uma contribuição valiosa, ele não precisou adicionar esses boatos úteis, e sua resposta o torna menos provável de fazê-lo na próxima vez.
— KomodoDave

2
Não estou "punindo" ninguém - isso é uma completa interpretação incorreta do que eu estava dizendo para @seh. O que quero dizer é que os comentários dele acrescentaram tanto que valia a pena e, de fato, mudaram tanto que achei que isso merecia uma resposta própria. Tenho certeza de que Sean Patrick Floyd não está preocupado com o parabéns, apenas ajudando os outros e ficaria perfeitamente feliz em fornecer sua própria resposta. Eu estava apenas encorajando seh, pois senti que sua contribuição merecia maior visibilidade. Como é possível ler meu comentário como qualquer outra coisa completamente me intriga, mas peço desculpas seh de alguma forma.
— RedYeti

1
Eu gosto de como essas discussões são retomadas depois de ficarem inativas por um tempo. Talvez a melhor coisa a fazer aqui seja editar a resposta de Sean, aumentando-a com minhas sugestões. Dessa forma, Sean continuará recebendo o crédito, a menos que a resposta seja transferida para o status do wiki da comunidade.
— 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();
}

Pensei em usar o Character.isDigit (), mas ele também aceita alguns caracteres que não são de 0 a 9 (consulte a documentação: download.oracle.com/javase/6/docs/api/java/lang/… )
— Sean Patrick Floyd

21

Usando o Google Guava:

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

ATUALIZAR:

O uso do CharMatcher pré-computado pode melhorar ainda mais o desempenho

CharMatcher ASCII_DIGITS=CharMatcher.inRange('0','9').precomputed();  
ASCII_DIGITS.retainFrom("123-456-789");

3
Agora está Charmatcher.DIGITpredefinido.
— Duncan McGregor

15
input.replaceAll("[^0-9?!\\.]","")

Isso ignorará os pontos decimais.

por exemplo: se você tiver uma entrada como 445.3kgserá a saída 445.3.


Eu tenho "4.5 zi". não está funcionando porque mantém o segundo. também
— Marian Klühspies

11

Usando o Google Guava:

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

O CharMatcher é plugável e bastante interessante de usar, por exemplo, você pode fazer o seguinte:

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

saída == 123-456-789


Solução muito boa (+1), mas sofre do mesmo problema que os outros: muitos caracteres se qualificam como dígitos unicode, não apenas os dígitos ascii. Este código manterá todos esses caracteres: unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D
— Sean Patrick Floyd

@seanizer: Então será melhor CharMatcher.inRange ('1', '9'). reterFrom ("123-456-789")
— Emil

@Emil mais como CharMatcher.inRange ('0', '9'), mas: sim
— Sean Patrick Floyd

inRange é o que está por trás do CharMatcher.DIGIT; pastie.org/1252471 Simplesmente leva em consideração os intervalos de números UTF, eu ainda os consideraria como dígitos, pois na realidade eles são, eles simplesmente não são codificados em ASCII.
— Bjorns

Você também pode usar CharMatcher.JAVA_DIGIT para a mesma finalidade, que aceitará apenas dígitos conforme Character.isDigit
— BjornS

6

Use expressão regular para corresponder aos seus 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);                 
}

5

Inspirei-me no código Sean Patrick Floyd e pouco o reescrevi para obter o máximo desempenho que recebo.

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

Eu faço o teste de desempenho para uma string muito longa com números mínimos e o resultado é:

  • O código original é 25,5% mais lento
  • A abordagem da goiaba é 2,5-3 vezes mais lenta
  • A expressão regular com D + é 3-3,5 vezes mais lenta
  • Expressão regular com apenas D é 25 vezes mais lenta

Btw depende de quanto tempo essa cadeia é. Com uma string que contém apenas 6 números, a goiaba é 50% mais lenta e a regexp 1 vezes mais lenta


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

Saída: 11



2

Finalizei o código para os números de telefone +9 (987) 124124.

Caracteres Unicode ocupam 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 );
}

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

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) ;
       }
       }
    }
 }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.