Bagaimana cara mengekstrak angka dari string dan mendapatkan array int?

109

Saya memiliki variabel String (pada dasarnya kalimat bahasa Inggris dengan jumlah angka yang tidak ditentukan) dan saya ingin mengekstrak semua angka ke dalam array bilangan bulat. Saya bertanya-tanya apakah ada solusi cepat dengan ekspresi reguler?


Saya menggunakan solusi Sean dan mengubahnya sedikit:

LinkedList<String> numbers = new LinkedList<String>();

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(line); 
while (m.find()) {
   numbers.add(m.group());
}
John Manak
sumber
1
Apakah angka diapit oleh spasi atau karakter lain? Bagaimana bilangan diformat, apakah itu heksadesimal, oktal, biner, desimal?
Buhake Sindi
Saya pikir sudah jelas dari pertanyaannya: ini adalah kalimat bahasa Inggris dengan angka. Selain itu saya berbicara tentang array integer, jadi yang saya cari adalah integer.
John Manak

Jawaban:

175
Pattern p = Pattern.compile("-?\\d+");
Matcher m = p.matcher("There are more than -2 and less than 12 numbers here");
while (m.find()) {
  System.out.println(m.group());
}

... mencetak -2dan 12.


-? cocok dengan tanda negatif utama - secara opsional. \ d cocok dengan digit, dan kita perlu menulis \seperti \\dalam String Java. Jadi, \ d + cocok dengan 1 digit atau lebih.

Sean Owen
sumber
4
Bisakah Anda melengkapi jawaban Anda dengan menjelaskan ekspresi reguler Anda?
OscarRyz
3
-? cocok dengan tanda negatif utama - secara opsional. \ d cocok dengan digit, dan kita perlu menulis \ sebagai \\ dalam String Java. Jadi, \\ d + mencocokkan 1 digit lagi
Sean Owen
7
Saya mengubah ekspresi saya menjadi Pattern.compile ("-? [\\ d \\.] +") Untuk mendukung float. Anda pasti membawa saya ke jalan, Thx!
jlengrand
Metode ini mendeteksi angka tetapi tidak mendeteksi angka yang diformat, misalnya 2,000. Untuk penggunaan seperti itu-?\\d+,?\\d+|-?\\d+
Mugoma J. Okomba
Itu hanya mendukung satu koma, jadi akan kehilangan "2.000.000". Ia juga menerima string seperti "2,00". Jika pemisah koma harus didukung, maka: -?\\d+(,\\d{3})*seharusnya berfungsi.
Sean Owen
52

Bagaimana menggunakan replaceAllmetode java.lang.String:

    String str = "qwerty-1qwerty-2 455 f0gfg 4";      
    str = str.replaceAll("[^-?0-9]+", " "); 
    System.out.println(Arrays.asList(str.trim().split(" ")));

Keluaran:

[-1, -2, 455, 0, 4]

Deskripsi

[^-?0-9]+
  • [dan ]membatasi sekumpulan karakter menjadi satu pencocokan, yaitu, hanya satu kali dalam urutan apa pun
  • ^Pengenal khusus yang digunakan di awal kumpulan, digunakan untuk menunjukkan agar cocok dengan semua karakter yang tidak ada dalam kumpulan yang dipisahkan, alih-alih semua karakter yang ada di kumpulan.
  • + Antara satu dan waktu tak terbatas, sebanyak mungkin, memberi kembali sesuai kebutuhan
  • -? Salah satu karakter “-” dan “?”
  • 0-9 Karakter dalam rentang antara "0" dan "9"
Maxim Shoustin
sumber
4
Mengapa Anda ingin menyimpan tanda tanya? Juga, ini memperlakukan -dengan sendirinya sebagai angka, bersama dengan hal-hal seperti 9-, ---6, dan 1-2-3.
Alan Moore
1
Alternatif yang sangat bagus tanpa menggunakan perpustakaan impor;)
Jcc. Sanabria
18
Pattern p = Pattern.compile("[0-9]+");
Matcher m = p.matcher(myString);
while (m.find()) {
    int n = Integer.parseInt(m.group());
    // append n to list
}
// convert list to array, etc

Anda sebenarnya dapat mengganti [0-9] dengan \ d, tetapi itu melibatkan pelolosan garis miring terbalik ganda, yang membuatnya lebih sulit untuk dibaca.

yg berkenaan dgn bintang
sumber
Ups. Sean menangani angka negatif, jadi itu peningkatan.
sidereal
2
milik Anda akan menangani angka negatif juga jika Anda menggunakan "-? [0-9] +"
cegprakash
9
  StringBuffer sBuffer = new StringBuffer();
  Pattern p = Pattern.compile("[0-9]+.[0-9]*|[0-9]*.[0-9]+|[0-9]+");
  Matcher m = p.matcher(str);
  while (m.find()) {
    sBuffer.append(m.group());
  }
  return sBuffer.toString();

Ini untuk mengekstraksi angka yang mempertahankan desimal

Kannan
sumber
Tidak menangani hal negatif
OneCricketeer
5

Jawaban yang diterima mendeteksi angka tetapi tidak mendeteksi angka yang diformat, misalnya 2.000, atau desimal, misalnya 4.8. Untuk penggunaan seperti itu -?\\d+(,\\d+)*?\\.?\\d+?:

        Pattern p = Pattern.compile("-?\\d+(,\\d+)*?\\.?\\d+?");
        List<String> numbers = new ArrayList<String>();
        Matcher m = p.matcher("Government has distributed 4.8 million textbooks to 2,000 schools");
        while (m.find()) {  
            numbers.add(m.group());
        }   
        System.out.println(numbers);

Keluaran: [4.8, 2,000]

Mugoma J. Okomba
sumber
1
@ JulienS .: Saya tidak setuju. Regex ini melakukan lebih dari yang diminta OP, dan tidak benar. (Setidaknya, bagian desimal harus berada dalam grup opsional, dengan semua isinya diperlukan dan serakah:. (?:\.\d+)?)
Alan Moore
Anda pasti mendapat poin di sana untuk bagian desimal. Namun, sangat umum menemukan angka yang diformat.
Julien
@AlanMoore banyak pengunjung SO mencari cara apa pun / berbeda untuk menyelesaikan masalah dengan berbagai kesamaan / perbedaan, dan saran tersebut akan sangat membantu. Bahkan OP mungkin terlalu menyederhanakan.
Mugoma J. Okomba
4

untuk bilangan rasional gunakan yang ini: (([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))

Andrey
sumber
1
OP mengatakan bilangan bulat, bukan bilangan real. Juga, Anda lupa untuk menghilangkan titik-titik tersebut, dan tidak ada tanda kurung yang diperlukan.
Alan Moore
3

Menggunakan Java 8, Anda dapat melakukan:

String str = "There 0 are 1 some -2-34 -numbers 567 here 890 .";
int[] ints = Arrays.stream(str.replaceAll("-", " -").split("[^-\\d]+"))
                 .filter(s -> !s.matches("-?"))
                 .mapToInt(Integer::parseInt).toArray();
System.out.println(Arrays.toString(ints)); // prints [0, 1, -2, -34, 567, 890]

Jika Anda tidak memiliki angka negatif, Anda dapat menyingkirkan replaceAll(dan penggunaan !s.isEmpty()di filter), karena itu hanya untuk sesuatu yang benar perpecahan seperti 2-34(ini juga bisa ditangani murni dengan regex di split, tapi itu cukup rumit).

Arrays.streammengubah kami String[]menjadi Stream<String>.

filtermenghilangkan string kosong di depan dan di belakangnya serta -yang bukan bagian dari angka.

mapToInt(Integer::parseInt).toArray()memanggil parseIntmasing String- masing untuk memberi kami int[].


Atau, Java 9 memiliki metode Matcher.results , yang memungkinkan sesuatu seperti:

Pattern p = Pattern.compile("-?\\d+");
Matcher m = p.matcher("There 0 are 1 some -2-34 -numbers 567 here 890 .");
int[] ints = m.results().map(MatchResults::group).mapToInt(Integer::parseInt).toArray();
System.out.println(Arrays.toString(ints)); // prints [0, 1, -2, -34, 567, 890]

Seperti berdiri, tidak satu pun dari ini merupakan peningkatan besar dari hanya mengulang hasil dengan Pattern/ Matcherseperti yang ditunjukkan pada jawaban lain, tetapi harus lebih sederhana jika Anda ingin menindaklanjutinya dengan operasi yang lebih kompleks yang secara signifikan disederhanakan dengan penggunaan aliran.

Bernhard Barker
sumber
1

Ekstrak semua bilangan real menggunakan ini.

public static ArrayList<Double> extractNumbersInOrder(String str){

    str+='a';
    double[] returnArray = new double[]{};

    ArrayList<Double> list = new ArrayList<Double>();
    String singleNum="";
    Boolean numStarted;
    for(char c:str.toCharArray()){

        if(isNumber(c)){
            singleNum+=c;

        } else {
            if(!singleNum.equals("")){  //number ended
                list.add(Double.valueOf(singleNum));
                System.out.println(singleNum);
                singleNum="";
            }
        }
    }

    return list;
}


public static boolean isNumber(char c){
    if(Character.isDigit(c)||c=='-'||c=='+'||c=='.'){
        return true;
    } else {
        return false;
    }
}
Kesombongan 68
sumber
1

Pecahan dan pengelompokan karakter untuk mewakili bilangan real mungkin berbeda antar bahasa. Bilangan real yang sama dapat ditulis dengan cara yang sangat berbeda tergantung pada bahasanya.

Angka dua juta di Jerman

2.000.000,00

dan dalam bahasa Inggris

2.000.000,00

Sebuah metode untuk sepenuhnya mengekstrak bilangan real dari string yang diberikan dengan cara tanpa bahasa:

public List<BigDecimal> extractDecimals(final String s, final char fraction, final char grouping) {
    List<BigDecimal> decimals = new ArrayList<BigDecimal>();
    //Remove grouping character for easier regexp extraction
    StringBuilder noGrouping = new StringBuilder();
    int i = 0;
    while(i >= 0 && i < s.length()) {
        char c = s.charAt(i);
        if(c == grouping) {
            int prev = i-1, next = i+1;
            boolean isValidGroupingChar =
                    prev >= 0 && Character.isDigit(s.charAt(prev)) &&
                    next < s.length() && Character.isDigit(s.charAt(next));                 
            if(!isValidGroupingChar)
                noGrouping.append(c);
            i++;
        } else {
            noGrouping.append(c);
            i++;
        }
    }
    //the '.' character has to be escaped in regular expressions
    String fractionRegex = fraction == POINT ? "\\." : String.valueOf(fraction);
    Pattern p = Pattern.compile("-?(\\d+" + fractionRegex + "\\d+|\\d+)");
    Matcher m = p.matcher(noGrouping);
    while (m.find()) {
        String match = m.group().replace(COMMA, POINT);
        decimals.add(new BigDecimal(match));
    }
    return decimals;
}
Dan kita
sumber
1

Jika Anda ingin mengecualikan angka yang ada dalam kata, seperti bar1 atau aa1bb, tambahkan batas kata \ b ke jawaban berbasis ekspresi reguler. Sebagai contoh:

Pattern p = Pattern.compile("\\b-?\\d+\\b");
Matcher m = p.matcher("9There 9are more9 th9an -2 and less than 12 numbers here9");
while (m.find()) {
  System.out.println(m.group());
}

menampilkan:

2
12
dxl
sumber
1

Saya akan menyarankan untuk memeriksa nilai ASCII untuk mengekstrak angka dari String Misalkan Anda memiliki String input sebagai myname12345 dan jika Anda ingin mengekstrak angka 12345 Anda dapat melakukannya dengan terlebih dahulu mengubah String menjadi Array Karakter kemudian gunakan pseudocode berikut

    for(int i=0; i < CharacterArray.length; i++)
    {
        if( a[i] >=48 && a[i] <= 58)
            System.out.print(a[i]);
    }

setelah nomor diekstraksi tambahkan ke array

Semoga ini membantu

The_Fresher
sumber
String Java dihitung urutan unit kode Unicode / UTF-16. Dengan desain UTF-16 128 karakter pertama memiliki nilai yang sama (dengan tidak berukuran sama) sebagai pengkodean ASCII mereka; Selain itu, berpikir Anda berurusan dengan ASCII akan menyebabkan kesalahan.
Tom Blodget
0

Saya menemukan ungkapan ini paling sederhana

String[] extractednums = msg.split("\\\\D++");
pengguna2902302
sumber
-1
public static String extractNumberFromString(String number) {
    String num = number.replaceAll("[^0-9]+", " ");
    return num.replaceAll(" ", "");
}

mengekstrak hanya angka dari string

pengguna3509903
sumber