Trích xuất các chữ số từ một chuỗi trong Java


207

Tôi có một Stringđối tượng Java . Tôi chỉ cần trích xuất các chữ số từ nó. Tôi sẽ đưa ra một ví dụ:

"123-456-789" tôi muốn "123456789"

Có một chức năng thư viện chỉ trích xuất các chữ số?

Cảm ơn câu trả lời. Trước khi thử, tôi cần biết tôi có phải cài đặt thêm bất kỳ thư viện nào không?

Câu trả lời:


545

Bạn có thể sử dụng regex và xóa các chữ số không.

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

6
mã ngắn đẹp. Một tìm kiếm tuyến tính có thể nhanh hơn nhưng tôi nghĩ rằng bạn có ý nghĩa hơn.
kasten

18
Tôi đoán bạn có thể downvote bất cứ điều gì bạn muốn downvote (không có ý định mỉa mai). Nhưng ý kiến ​​cá nhân của tôi là: khi các nhà phát triển tuyệt vời (và chúng tôi có rất nhiều người trong số họ ở đây) chia sẻ một số lời khuyên của họ miễn phí, thì tôi sẽ tôn trọng điều đó, và tôi chỉ đánh giá thấp những thứ thực sự khủng khiếp (kiểm tra hồ sơ của tôi, hiện tại của tôi tỷ lệ là 14xx so với 17 xuống). Nhưng đó là triết lý cá nhân của tôi và bạn có thể tự do sở hữu.
Sean Patrick Floyd

78
Điều này sẽ không hoạt động nếu số của bạn có dấu thập phân, nó cũng loại bỏ dấu thập phân. str = str.replaceAll("[^\\.0123456789]","");
Aravindan R

2
Mặc dù regex cực kỳ đơn giản và dễ nhìn, nhưng nó bị các vấn đề về hiệu năng và chỉ nên được sử dụng khi bạn có một dải một lần (như gửi biểu mẫu). Nếu bạn đang xử lý nhiều dữ liệu, đây không phải là cách để đi.
Brill Pappin

2
và nếu bạn cần loại trừ bất cứ điều gì, như dấu thập phân,(?!\\.)
azerafati

49

Đây là một giải pháp dài dòng hơn. Ít thanh lịch, nhưng có lẽ nhanh hơn:

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

Mã kiểm tra:

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

Đầu ra:

0123456789

BTW: Tôi không sử dụng Character.isDigit (ch) vì nó chấp nhận nhiều ký tự khác ngoại trừ 0 - 9.


4
Bạn nên cung cấp kích thước cho hàm StringBuildertạo (chẳng hạn như input.length()) để đảm bảo rằng nó sẽ không cần phân bổ lại. Bạn không cần phải yêu cầu Stringở đây; CharSequenceđủ. Ngoài ra, bạn có thể tách phân bổ của StringBuilderbộ sưu tập các chữ số không bằng cách viết một hàm riêng chấp nhận một CharSequenceđầu vào và một Appendablethể hiện như một bộ tích lũy đầu ra.
seh

1
@seh Nghe có vẻ thú vị nhưng thay vì bình luận tại sao không tạo câu trả lời của riêng bạn với các phần mở rộng?
RedYeti

3
@RedYeti Để câu trả lời này vẫn còn và thêm một bình luận là vinh dự hơn kể từ khi Sean nhận được upvotes sau đó. Việc phê bình mã của người khác cũng nhanh hơn rất nhiều so với viết lại nếu bạn đang vội. Đừng trừng phạt seh vì đã đóng góp có giá trị, anh ấy đã không phải thêm những mẩu tin hữu ích đó và phản ứng của bạn khiến anh ấy ít có khả năng làm điều đó vào lần tới.
KomodoDave

2
Tôi không "trừng phạt" bất cứ ai - đó là một sự giải thích sai hoàn toàn những gì tôi đang nói với @seh. Quan điểm của tôi là những bình luận của anh ấy đã bổ sung rất nhiều thứ đáng giá và thực tế đã thay đổi rất nhiều đến nỗi tôi cảm thấy nó đảm bảo một câu trả lời của chính nó. Tôi chắc chắn Sean Patrick Floyd không quan tâm đến việc chỉ giúp đỡ người khác và sẽ hoàn toàn hài lòng với câu trả lời của chính mình. Tôi chỉ đơn thuần là khuyến khích seh vì tôi cảm thấy sự đóng góp của anh ấy xứng đáng được nhìn thấy nhiều hơn. Làm thế nào có thể đọc bình luận của tôi như bất cứ điều gì khác hoàn toàn đánh đố tôi nhưng tôi xin lỗi seh nếu nó bằng cách nào đó đã làm.
RedYeti

1
Tôi thích cách các cuộc thảo luận này diễn ra sau khi nằm im một lúc. Có lẽ điều tốt nhất để làm ở đây là để tôi chỉnh sửa câu trả lời của Sean, làm tăng thêm nó bằng những gợi ý của tôi. Bằng cách đó, Sean sẽ tiếp tục nhận được tín dụng trừ khi câu trả lời chuyển sang trạng thái wiki cộng đồng.
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();
}

Bản thân tôi đã nghĩ đến việc sử dụng Character.isDigit (), nhưng nó cũng chấp nhận một số ký tự không phải là 0-9 (xem tài liệu: download.oracle.com/javase/6/docs/api/java/lang/ trộm )
Sean Patrick Floyd

21

Sử dụng Google ổi:

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

CẬP NHẬT:

Sử dụng CharMatcher được tính toán trước có thể cải thiện hiệu suất hơn nữa

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

3
Hiện tại đã Charmatcher.DIGITđược xác định trước.
Duncan McGregor

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

Điều này sẽ bỏ qua các dấu thập phân.

ví dụ: nếu bạn có một đầu vào là 445.3kgđầu ra sẽ là 445.3.


Tôi có "4,5 zi." không hoạt động vì nó giữ thứ hai. cũng vậy
Marian Klühspies

11

Sử dụng Google ổi:

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

CharMatcher có khả năng cắm và khá thú vị khi sử dụng, ví dụ bạn có thể làm như sau:

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

đầu ra == 123-456-789


Giải pháp rất hay (+1), nhưng nó cũng gặp phải vấn đề tương tự như các vấn đề khác: rất nhiều ký tự đủ điều kiện là chữ số unicode, không chỉ các chữ số ascii. Mã này sẽ giữ lại tất cả các ký tự này: unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D
Sean Patrick Floyd

@seanizer: Sau đó, điều này sẽ tốt hơn CharMatcher.inRange ('1', '9'). Giữ lại từ ("123-456-789")
Emil

@Emil giống như CharMatcher.inRange ('0', '9'), nhưng: có
Sean Patrick Floyd

inRange là những gì nằm sau CharMatcher.DIGIT; pastie.org/1252471 Nó chỉ đơn giản là tính đến các phạm vi số UTF có điều kiện, tôi vẫn sẽ coi đây là các chữ số, vì trong thực tế, chúng đơn giản không phải là mã hóa ASCII.
BjornS

Bạn cũng có thể sử dụng CharMatcher.JAVA_DIGIT cho cùng một mục đích, điều đó sẽ chỉ chấp nhận các chữ số theo Nhân
vật.isDigit

6

Sử dụng biểu thức chính quy để phù hợp với yêu cầu của bạn.

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

Tôi lấy cảm hứng từ mã Sean Patrick Floyd và ít viết lại nó để đạt hiệu suất tối đa tôi nhận được.

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

Tôi thực hiện kiểm tra Hiệu suất cho Chuỗi rất dài với số lượng tối thiểu và kết quả là:

  • Mã gốc chậm hơn 25,5%
  • Cách tiếp cận ổi chậm hơn 2,5-3 lần
  • Biểu thức chính quy với D + chậm hơn 3-3,5 lần
  • Biểu thức chính quy chỉ có D chậm hơn 25 lần

Btw nó phụ thuộc vào chuỗi đó dài bao nhiêu. Với chuỗi chỉ chứa 6 số là ổi chậm hơn 50% và chậm hơn 1 lần


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

Đầu ra: 11



2

Tôi đã hoàn tất mã cho số điện thoại +9 (987) 124124.

Ký tự Unicode chiếm 4 byte.

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

Mã số:

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) ;
       }
       }
    }
 }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.