แยกตัวเลขจากสตริงใน Java


207

ฉันมีStringวัตถุJava ฉันต้องการแยกเฉพาะตัวเลขจากมัน ฉันจะให้ตัวอย่าง:

"123-456-789" ฉันต้องการ "123456789"

มีฟังก์ชั่นห้องสมุดที่แยกตัวเลขเท่านั้นหรือไม่

ขอบคุณสำหรับคำตอบ ก่อนที่ฉันจะลองสิ่งเหล่านี้ฉันต้องรู้ว่าฉันจะต้องติดตั้งห้องสมุดเพิ่มเติมหรือไม่?

คำตอบ:


546

คุณสามารถใช้ regex และลบไม่ใช่ตัวเลข

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

6
รหัสย่อที่ดี การค้นหาเชิงเส้นอาจเร็วกว่านี้ แต่ฉันคิดว่าคุณสมเหตุสมผลกว่า
kasten

18
ฉันเดาว่าคุณสามารถโหวตทุกสิ่งที่คุณต้องการลงคะแนนได้ แต่ความเห็นส่วนตัวของฉันคือ: เมื่อนักพัฒนาที่ยอดเยี่ยม (และเรามีพวกเขามากมายที่นี่) แบ่งปันคำแนะนำบางอย่างฟรีแล้วฉันจะให้เกียรตินั้นและฉันเพียงคัดค้านสิ่งที่แย่มาก อัตราส่วนคือ 14xx ขึ้นกับ 17 ลง) แต่นั่นคือปรัชญาส่วนตัวของฉันและคุณมีอิสระที่จะมีของคุณเอง
ฌอนแพทริคฟลอยด์

78
สิ่งนี้จะไม่ทำงานหากหมายเลขของคุณมีจุดทศนิยมมันจะลบจุดทศนิยมเช่นกัน str = str.replaceAll("[^\\.0123456789]","");
Aravindan R

2
แม้ว่า regex นั้นง่ายมากและดูสะอาดตา แต่ก็มีปัญหาเรื่องประสิทธิภาพการทำงานและควรใช้เมื่อคุณมีแถบเปิดปิดแบบครั้งเดียวเท่านั้น (เช่นส่งแบบฟอร์ม) หากคุณกำลังประมวลผลข้อมูลจำนวนมากนี่ไม่ใช่วิธีที่จะไป
Brill Pappin สุดยอด

2
และถ้าคุณต้องการยกเว้นสิ่งใด ๆ เช่นจุดทศนิยม(?!\\.)
azerafati

49

นี่คือวิธีแก้ปัญหา verbose เพิ่มเติม สง่างามน้อยลง แต่อาจเร็วกว่า:

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

รหัสทดสอบ:

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

เอาท์พุท:

0123456789

BTW: ฉันไม่ได้ใช้Character.isDigit (ch)เพราะมันยอมรับตัวอักษรอื่น ๆ อีกมากมายยกเว้น 0 - 9


4
คุณควรระบุขนาดให้กับตัวStringBuilderสร้าง (เช่นinput.length()) เพื่อให้แน่ใจว่าไม่จำเป็นต้องจัดสรรใหม่ คุณไม่จำเป็นต้องมีStringที่นี่ CharSequenceพอเพียง นอกจากนี้คุณสามารถแยกการจัดสรรStringBuilderจากการรวบรวมของไม่ใช่ตัวเลขโดยการเขียนฟังก์ชั่นแยกต่างหากที่ยอมรับCharSequenceเป็นอินพุตและAppendableอินสแตนซ์เป็นตัวสะสมเอาท์พุท
seh

1
@seh ฟังดูน่าสนใจ แต่แทนที่จะแสดงความคิดเห็นว่าทำไมไม่สร้างคำตอบของคุณเองด้วยส่วนขยาย
RedYeti

3
@RedYeti ปล่อยให้คำตอบนี้ยังคงอยู่และเพิ่มความคิดเห็นมีเกียรติมากขึ้นตั้งแต่ฌอนได้รับ upvotes แล้ว นอกจากนี้ยังเร็วกว่ามากในการวิจารณ์โค้ดของผู้อื่นมากกว่าเขียนใหม่หากคุณรีบ อย่าลงโทษ seh เพราะทำสิ่งที่มีค่าเขาไม่ต้องเพิ่มเกร็ดเล็กเกร็ดน้อยที่มีประโยชน์เหล่านั้นและการตอบสนองของคุณทำให้เขามีโอกาสน้อยลงที่จะทำเช่นนั้นในครั้งต่อไป
KomodoDave

2
ฉันไม่ได้ "ลงโทษ" ใคร - นั่นเป็นการตีความที่ผิดอย่างสมบูรณ์ในสิ่งที่ฉันพูดกับ @seh ประเด็นของฉันคือความคิดเห็นของเขาเพิ่มมากซึ่งคุ้มค่าและในความเป็นจริงก็เปลี่ยนไปมากจนฉันรู้สึกว่ามันรับประกันคำตอบของมันเอง ฉันแน่ใจว่าฌอนแพทริคฟลอยด์ไม่ได้เกี่ยวข้องกับความรุ่งโรจน์เพียงช่วยเหลือผู้อื่นและจะมีความสุขอย่างสมบูรณ์กับ seh ให้คำตอบของเขาเอง ฉันแค่ให้กำลังใจ seh เพราะฉันรู้สึกว่าการมีส่วนร่วมของเขาสมควรได้รับการเปิดเผยมากขึ้น เป็นไปได้อย่างไรที่จะอ่านความคิดเห็นของฉันเป็นอย่างอื่นทำให้ฉันไขปริศนาได้อย่างสมบูรณ์ แต่ฉันต้องขออภัยที่จะตรวจสอบว่ามันทำอย่างใด
RedYeti

1
ฉันชอบวิธีที่การสนทนาเหล่านี้ดีขึ้นหลังจากนอนเฉยๆสักพัก บางทีสิ่งที่ดีที่สุดที่จะทำที่นี่คือให้ฉันแก้ไขคำตอบของฌอนโดยเพิ่มคำแนะนำของฉัน ด้วยวิธีนี้ฌอนจะยังคงได้รับเครดิตต่อไปเว้นแต่คำตอบจะเปลี่ยนเป็นสถานะวิกิชุมชน
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();
}

ฉันคิดว่าจะใช้ Character.isDigit () ด้วยตัวเอง แต่ก็ยอมรับอักขระบางตัวที่ไม่ใช่ 0-9 (ดูเอกสาร: download.oracle.com/javase/6/docs/api/java/lang/… )
Sean Patrick ฟลอยด์

21

ใช้ Google Guava:

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

UPDATE:

การใช้CharMatcher Precomputedสามารถปรับปรุงประสิทธิภาพได้อีก

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

3
ขณะนี้มีการCharmatcher.DIGITกำหนดไว้ล่วงหน้า
Duncan McGregor

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

นี่จะเป็นการละเว้นจุดทศนิยม

เช่นถ้าคุณมีการป้อนข้อมูลเป็นผลลัพธ์จะ445.3kg445.3


ฉันมี "4.5 zi" ไม่ทำงานเพราะมันคงอยู่ที่สอง เกินไป
แมเรียนKlühspies

11

ใช้ Google Guava:

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

CharMatcher สามารถใช้ปลั๊กอินและค่อนข้างน่าสนใจเช่นคุณสามารถทำสิ่งต่อไปนี้:

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

เอาท์พุท == 123-456-789


วิธีแก้ปัญหาที่ดีมาก (+1) แต่ได้รับผลกระทบจากปัญหาเดียวกันกับปัญหาอื่น ๆ : อักขระจำนวนมากมีคุณสมบัติเป็นตัวเลข Unicode ไม่ใช่เฉพาะตัวเลข ASCII รหัสนี้จะเก็บอักขระเหล่านี้ทั้งหมด: unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D
Sean Patrick Floyd

@seanizer: ถ้าอย่างนั้นจะดีกว่า CharMatcher.inRange ('1', '9'). keepFrom ("123-456-789")
Emil

@Emil ชอบ CharMatcher.inRange ('0', '9') แต่: ใช่
Sean Patrick Floyd

inRange คือสิ่งที่อยู่เบื้องหลัง CharMatcher.DIGIT; pastie.org/1252471 มันแค่คำนึงถึงช่วงหมายเลข UTF แบบมีเหตุผลฉันจะยังคงพิจารณาตัวเลขเหล่านี้เป็นตัวเลขเนื่องจากในความเป็นจริงแล้วพวกเขาจะไม่เข้ารหัส ASCII
BjornS

นอกจากนี้คุณยังสามารถใช้ CharMatcher.JAVA_DIGIT เพื่อจุดประสงค์เดียวกันซึ่งจะยอมรับเฉพาะตัวเลขตามตัวละครตัวละครหลัก
BjornS

6

ใช้นิพจน์ทั่วไปเพื่อให้ตรงกับความต้องการของคุณ

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

ฉันได้แรงบันดาลใจจากรหัส Sean Patrick Floyd และเขียนใหม่อีกครั้งเพื่อประสิทธิภาพสูงสุดที่ฉันได้รับ

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

ฉันจะทดสอบประสิทธิภาพเพื่อสตริงที่ยาวมากที่มีตัวเลขน้อยที่สุดและผลคือ:

  • รหัสเดิมช้ากว่า 25,5%
  • วิธีฝรั่งช้ากว่า 2.5-3 เท่า
  • นิพจน์ทั่วไปที่มี D + ช้ากว่า 3-3.5 เท่า
  • นิพจน์ทั่วไปที่มีเพียง D จะช้ากว่า 25+ ครั้ง

Btw มันขึ้นอยู่กับว่าสตริงนั้นนานแค่ไหน ด้วยสตริงที่มีเพียง 6 หมายเลขฝรั่งจะช้าลง 50% และ regexp ช้าลง 1 เท่า


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

ผลลัพธ์: 11



2

ฉันได้สรุปรหัสสำหรับหมายเลขโทรศัพท์ +9 (987) 124124

อักขระ Unicode มีขนาด 4 ไบต์

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


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) ;
       }
       }
    }
 }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.