Extrahieren Sie Ziffern aus einer Zeichenfolge in Java


207

Ich habe ein Java- StringObjekt. Ich muss nur Ziffern daraus extrahieren. Ich werde ein Beispiel geben:

"123-456-789" Ich will "123456789"

Gibt es eine Bibliotheksfunktion, die nur Ziffern extrahiert?

Danke für die Antworten. Bevor ich diese versuche, muss ich wissen, ob ich zusätzliche Bibliotheken installieren muss.

Antworten:


545

Sie können Regex verwenden und Nicht-Ziffern löschen.

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

6
schöner Funktionscode. Eine lineare Suche mag schneller sein, aber ich denke, deine macht mehr Sinn.
Kasten

18
Ich denke, Sie können alles ablehnen, was Sie ablehnen möchten (kein Sarkasmus beabsichtigt). Aber meine persönliche Meinung ist: Wenn großartige Entwickler (und wir haben viele von ihnen hier) einige ihrer Ratschläge kostenlos teilen, werde ich das honorieren und nur Dinge ablehnen, die wirklich schrecklich sind (überprüfen Sie mein Profil, mein aktuelles Verhältnis ist 14xx hoch gegen 17 runter). Aber das ist meine persönliche Philosophie und Sie können Ihre eigene haben.
Sean Patrick Floyd

78
Dies funktioniert nicht, wenn Ihre Zahl einen Dezimalpunkt hat, sondern entfernt auch den Dezimalpunkt. str = str.replaceAll("[^\\.0123456789]","");
Aravindan R

2
Obwohl der Regex äußerst einfach und übersichtlich anzusehen ist, weist er Leistungsprobleme auf und sollte nur verwendet werden, wenn Sie einen einmaligen Streifen haben (wie das Senden eines Formulars). Wenn Sie viele Daten verarbeiten, ist dies nicht der richtige Weg.
Brill Pappin

2
und wenn Sie etwas wie einen Dezimalpunkt ausschließen müssen,(?!\\.)
azerafati

49

Hier ist eine ausführlichere Lösung. Weniger elegant, aber wahrscheinlich schneller:

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

Testcode:

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

Ausgabe:

0123456789

Übrigens: Ich habe Character.isDigit (ch) nicht verwendet, da es viele andere Zeichen außer 0 - 9 akzeptiert.


4
Sie sollten dem StringBuilderKonstruktor (z. B. input.length()) eine Größe bereitstellen, um sicherzustellen, dass er nicht neu zugewiesen werden muss. Sie müssen hier kein verlangen String; CharSequencegenügt. Sie können die Zuordnung von auch StringBuildervon der Sammlung nichtstelliger Zahlen trennen, indem Sie eine separate Funktion schreiben, die eine CharSequenceals Eingabe und eine AppendableInstanz als Ausgabespeicher akzeptiert .
seh

1
@seh Klingt interessant, aber anstatt zu kommentieren, warum nicht eine eigene Antwort mit den Erweiterungen erstellen?
RedYeti

3
@RedYeti Diese Antwort bleiben zu lassen und einen Kommentar hinzuzufügen ist ehrenwerter, da Sean dann positive Stimmen erhält. Es ist auch viel schneller, den Code anderer zu kritisieren, als ihn neu zu schreiben, wenn Sie es eilig haben. Bestrafen Sie seh nicht dafür, dass er einen wertvollen Beitrag geleistet hat, er musste diese nützlichen Leckerbissen nicht hinzufügen, und Ihre Antwort macht es weniger wahrscheinlich, dass er dies beim nächsten Mal tut.
KomodoDave

2
Ich "bestrafe" niemanden - das ist eine völlige Fehlinterpretation dessen, was ich @seh gesagt habe. Mein Punkt war, dass seine Kommentare so viel hinzufügten, was sich lohnte und sich tatsächlich so sehr änderte, dass ich der Meinung war, dass dies eine eigene Antwort rechtfertigte. Ich bin sicher, Sean Patrick Floyd kümmert sich nicht darum, dass Kudos nur anderen helfen, und würde sich sehr freuen, wenn er seine eigene Antwort geben würde. Ich habe seh nur ermutigt, da ich der Meinung war, dass sein Beitrag eine größere Sichtbarkeit verdient. Wie es möglich ist, meinen Kommentar zu lesen, da alles andere mich völlig verwirrt, aber ich entschuldige mich bei seh, wenn es irgendwie passiert ist.
RedYeti

1
Mir gefällt, wie diese Diskussionen nach einer Weile des Schlafens beginnen. Vielleicht ist es das Beste, hier Seans Antwort zu bearbeiten und sie mit meinen Vorschlägen zu ergänzen. Auf diese Weise erhält Sean weiterhin die Gutschrift, es sei denn, die Antwort wechselt in den Community-Wiki-Status.
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();
}

Ich habe darüber nachgedacht, Character.isDigit () selbst zu verwenden, aber es werden auch einige Zeichen akzeptiert, die nicht 0-9 sind (siehe Dokumente: download.oracle.com/javase/6/docs/api/java/lang/… )
Sean Patrick Floyd

21

Verwenden von Google Guava:

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

AKTUALISIEREN:

Die Verwendung von Precomputed CharMatcher kann die Leistung weiter verbessern

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

3
Es ist jetzt Charmatcher.DIGITvordefiniert.
Duncan McGregor

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

Dadurch werden die Dezimalstellen ignoriert.

Beispiel: Wenn Sie einen Eingang haben, wird 445.3kgder Ausgang sein 445.3.


Ich habe "4.5 zi". funktioniert nicht, weil es die zweite hält. auch
Marian Klühspies

11

Verwenden von Google Guava:

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

CharMatcher ist steckbar und sehr interessant zu bedienen. Sie können beispielsweise Folgendes tun:

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

Ausgabe == 123-456-789


Sehr schöne Lösung (+1), aber sie hat das gleiche Problem wie andere: Viele Zeichen gelten als Unicode-Ziffern, nicht nur als ASCII-Ziffern. Dieser Code behält alle diese Zeichen bei: unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D
Sean Patrick Floyd

@ Seanizer: Dann ist dies besser CharMatcher.inRange ('1', '9'). RetainFrom ("123-456-789")
Emil

@Emil eher wie CharMatcher.inRange ('0', '9'), aber: ja
Sean Patrick Floyd

inRange steckt hinter CharMatcher.DIGIT; pastie.org/1252471 Es werden lediglich die UTF-Nummernbereiche berücksichtigt, ich würde diese immer noch als Ziffern betrachten, da sie in Wirklichkeit einfach nicht ASCII-codiert sind.
Björn

Sie können auch CharMatcher.JAVA_DIGIT für den gleichen Zweck verwenden, der nur Ziffern gemäß Character.isDigit
BjornS

6

Verwenden Sie reguläre Ausdrücke, um Ihren Anforderungen zu entsprechen.

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

Ich habe mich vom Code Sean Patrick Floyd inspirieren lassen und ihn wenig umgeschrieben, um maximale Leistung zu erzielen.

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

Ich mache einen Leistungstest für einen sehr langen String mit minimalen Zahlen und das Ergebnis ist:

  • Der ursprüngliche Code ist 25,5% langsamer
  • Der Guavenansatz ist 2,5-3 mal langsamer
  • Der reguläre Ausdruck mit D + ist 3-3,5-mal langsamer
  • Der reguläre Ausdruck mit nur D ist mehr als 25 Mal langsamer

Übrigens hängt es davon ab, wie lang diese Zeichenfolge ist. Mit String, der nur 6 Zahlen enthält, ist Guave 50% langsamer und Regexp 1 mal langsamer


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

Ausgabe: 11



2

Ich habe den Code für die Telefonnummern +9 (987) 124124 festgelegt.

Unicode-Zeichen belegen 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

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

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) ;
       }
       }
    }
 }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.