Wyodrębnij cyfry z łańcucha znaków w Javie


207

Mam Stringobiekt Java . Muszę z niego wyodrębnić tylko cyfry. Podam przykład:

"123-456-789" chcę "123456789"

Czy istnieje funkcja biblioteki, która wyodrębnia tylko cyfry?

Dziękuję za odpowiedzi. Zanim spróbuję, muszę wiedzieć, czy muszę zainstalować dodatkowe biblioteki?

Odpowiedzi:


545

Możesz użyć wyrażenia regularnego i usuwać cyfry.

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

6
ładny krótki kod. Wyszukiwanie liniowe może być szybsze, ale myślę, że twoje ma sens.
kasten

18
Wydaje mi się, że możesz głosować wszystko, co lubisz głosować (bez zamierzonego sarkazmu). Ale moja osobista opinia jest taka: kiedy świetni programiści (a mamy ich tutaj wielu) dzielą się niektórymi swoimi poradami za darmo, to mam zamiar je uhonorować, a ja głosuję tylko to, co jest naprawdę okropne (sprawdź mój profil, mój obecny stosunek wynosi 14xx w porównaniu do 17 w dół). Ale to moja osobista filozofia i masz swobodę posiadania własnej.
Sean Patrick Floyd

78
To nie zadziała, jeśli twoja liczba ma przecinek dziesiętny, to również usuwa przecinek dziesiętny. str = str.replaceAll("[^\\.0123456789]","");
Aravindan R

2
Chociaż wyrażenie regularne jest wyjątkowo proste i przejrzyste, ma problemy z wydajnością i powinno być używane tylko wtedy, gdy masz jednorazowy pasek (jak przesyłanie formularza). Jeśli przetwarzasz dużo danych, nie jest to właściwa droga.
Brill Pappin,

2
a jeśli chcesz coś wykluczyć, na przykład przecinek dziesiętny,(?!\\.)
azerafati

49

Oto bardziej szczegółowe rozwiązanie. Mniej elegancki, ale prawdopodobnie szybszy:

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

Kod testowy:

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

Wynik:

0123456789

BTW: Nie użyłem Character.isDigit (ch), ponieważ akceptuje wiele innych znaków oprócz 0 - 9.


4
Należy podać rozmiar StringBuilderkonstruktorowi (np. input.length()), Aby upewnić się, że nie będzie musiał on ponownie przydzielać. Nie musisz żądać Stringtutaj; CharSequencewystarczy. Można także oddzielić alokację StringBuilderod zbioru niecyfrowego, pisząc osobną funkcję, która akceptuje CharSequencejako wejście i Appendableinstancję jako akumulator wyjściowy.
seh

1
@seh Brzmi interesująco, ale zamiast komentować, dlaczego nie stworzyć własnej odpowiedzi z rozszerzeniami?
RedYeti,

3
@RedYeti Pozostawienie tej odpowiedzi i dodanie komentarza jest bardziej honorowe, ponieważ Sean otrzymuje wówczas głosy poparcia. Dużo szybsze jest także krytykowanie kodu innych osób niż przepisywanie go, jeśli się spieszysz. Nie karaj seha za cenny wkład, nie musiał dodawać tych przydatnych ciekawostek, a twoja reakcja zmniejsza prawdopodobieństwo, że zrobi to następnym razem.
KomodoDave,

2
Nie „karzę” nikogo - to kompletna błędna interpretacja tego, co mówiłem @seh. Chodziło mi o to, że jego komentarze dodały tak wiele, co było wartościowe i faktycznie zmieniło się tak bardzo, że czułem, że uzasadnia to własną odpowiedź. Jestem pewien, że Sean Patrick Floyd nie interesuje się uznaniem tylko pomagania innym i byłby całkowicie szczęśliwy, gdyby seh udzielił własnej odpowiedzi. Po prostu zachęcałem, bo uważałem, że jego wkład zasługuje na większą widoczność. Jak to możliwe, aby przeczytać mój komentarz, ponieważ wszystko inne całkowicie mnie intryguje, ale przepraszam za seh, jeśli tak się stanie.
RedYeti

1
Podoba mi się, jak te dyskusje podejmują się po tym, jak przez jakiś czas leżą w stanie spoczynku. Być może najlepszą rzeczą, którą mogę tutaj zrobić, jest zredagowanie odpowiedzi Seana, powiększając ją o moje sugestie. W ten sposób Sean będzie nadal otrzymywać kredyt, chyba że odpowiedź przejdzie w stan wiki społeczności.
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();
}

Myślałem o użyciu Character.isDigit () osobiście, ale akceptuje także niektóre znaki, które nie są 0-9 (patrz dokumenty: download.oracle.com/javase/6/docs/api/java/lang/… )
Sean Patrick Floyd

21

Korzystanie z Google Guava:

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

AKTUALIZACJA:

Korzystanie ze wstępnie obliczonego CharMatchera może dodatkowo poprawić wydajność

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

3
Jest teraz Charmatcher.DIGITpredefiniowany.
Duncan McGregor,

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

To zignoruje przecinki dziesiętne.

np .: jeśli masz dane wejściowe takie, 445.3kgjakie będą dane wyjściowe 445.3.


Mam „4.5 zi”. nie działa, ponieważ utrzymuje drugi. też
Marian Klühspies

11

Korzystanie z Google Guava:

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

CharMatcher jest wtyczkowy i bardzo interesujący w użyciu, na przykład możesz wykonać następujące czynności:

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

wynik == 123-456-789


Bardzo fajne rozwiązanie (+1), ale ma ten sam problem co inne: wiele znaków kwalifikuje się jako cyfry Unicode, nie tylko cyfry ascii. Ten kod zachowa wszystkie te znaki: unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D
Sean Patrick Floyd

@seanizer: Czy będzie lepiej CharMatcher.inRange ('1', '9'). retainFrom ("123-456-789")
Emil

@Emil bardziej jak CharMatcher.inRange („0”, „9”), ale: tak
Sean Patrick Floyd

inRange jest tym, co kryje się za CharMatcher.DIGIT; pastie.org/1252471 Po prostu bierze pod uwagę zakresy liczb UTF, nadal uważam je za cyfry, ponieważ w rzeczywistości są one po prostu nie zakodowane w ASCII.
BjornS,

Możesz także użyć CharMatcher.JAVA_DIGIT w tym samym celu, który akceptuje tylko cyfry zgodnie z Character.isDigit
BjornS

6

Użyj wyrażenia regularnego, aby dopasować swoje wymagania.

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

Zainspirowałem się kodem Seana Patricka Floyda i trochę go przepisałem, aby uzyskać maksymalną wydajność.

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

wykonuję test wydajności na bardzo długim ciągu z minimalnymi liczbami, a wynik to:

  • Oryginalny kod jest o 25,5% wolniejszy
  • Podejście guawy jest 2,5-3 razy wolniejsze
  • Wyrażenie regularne z D + jest 3-3,5 razy wolniejsze
  • Wyrażenie regularne tylko z D jest ponad 25 razy wolniejsze

Btw zależy od tego, jak długi jest ten sznurek. Łańcuch zawierający tylko 6 liczb jest guawa o 50% wolniejszy i regexp 1 razy wolniejszy


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

Wyjście: 11



2

Sfinalizowałem kod dla numerów telefonów +9 (987) 124124.

Znaki Unicode zajmują 4 bajty.

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

Kod:

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) ;
       }
       }
    }
 }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.