Bir dizeden sayılar nasıl çıkarılır ve bir tamsayı dizisi elde edilir?


109

Bir String değişkenim var (temelde belirtilmemiş sayıda sayı içeren bir İngilizce cümle) ve tüm sayıları bir tamsayı dizisine çıkarmak istiyorum. Düzenli ifadelerle hızlı bir çözüm olup olmadığını merak ediyordum?


Sean'ın çözümünü kullandım ve biraz değiştirdim:

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

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(line); 
while (m.find()) {
   numbers.add(m.group());
}

1
Sayılar boşluklarla veya başka karakterlerle mi çevrilidir? Sayılar nasıl biçimlendirilir, onaltılık, sekizlik, ikili, ondalık mı?
Buhake Sindi

Sorudan anlaşılır olduğunu düşündüm: rakamlarla İngilizce bir cümle. Dahası bir tamsayı dizisinden bahsediyordum, yani aradığım şey tamsayılardı.
John Manak

Yanıtlar:


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

... baskılar -2ve 12.


-? isteğe bağlı olarak baştaki bir negatif işaretiyle eşleşir. \ d bir rakamla eşleşir ve yine de bir Java Dizesindeki \gibi yazmamız gerekir \\. Yani \ d +, 1 veya daha fazla rakamla eşleşir.


4
Lütfen cevabınızı normal ifadenizi açıklayarak tamamlayabilir misiniz?
OscarRyz

3
-? isteğe bağlı olarak baştaki bir negatif işaretiyle eşleşir. \ d bir rakamla eşleşir ve yine de bir Java Dizgesine \ olarak \\ yazmamız gerekir. Yani, \\ d + 1 basamak daha daha eşleşir
Sean Owen

7
Yüzen sayıları desteklemek için ifademi Pattern.compile ("-? [\\ d \\.] +") Olarak değiştirdim. Kesinlikle beni yolda yönlendiriyorsun, Thx!
jlengrand

Bu yöntem rakamları algılar ancak biçimlendirilmiş sayıları, örn 2,000. Bu tür kullanım için-?\\d+,?\\d+|-?\\d+
Mugoma J.Okomba

Bu sadece tek bir virgül destekler, bu yüzden "2.000.000" atlanır. Ayrıca "2,00" gibi dizeleri de kabul eder. Virgül ayırıcıların desteklenmesi gerekiyorsa, o zaman: -?\\d+(,\\d{3})*çalışmalıdır.
Sean Owen

52

replaceAllJava.lang.String yöntemini kullanmaya ne dersiniz :

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

Çıktı:

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

Açıklama

[^-?0-9]+
  • [ve ]tek eşleşecek bir karakter kümesini sınırlar, yani herhangi bir sırada yalnızca bir kez
  • ^Özel tanımlayıcı tüm karakterleri eşleştirmek için belirtmek için kullanılır, setin başında kullanılan değil tüm karakterlerin sette mevcut yerine sınırlandırılmış setinde mevcut.
  • + Bir ile sınırsız kez arasında, olabildiğince çok kez, gerektiği kadar geri vermek
  • -? "-" ve "?" Karakterlerinden biri
  • 0-9 "0" ile "9" aralığındaki bir karakter

4
Neden soru işaretleri tutmak istersiniz? Ayrıca, bu davranır -şeylerle birlikte bir sayı olarak tek başına, ister 9-, ---6ve 1-2-3.
Alan Moore

1
Kütüphaneleri içe aktarmadan çok güzel bir alternatif;)
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

Aslında [0-9] yerine \ d yazabilirsiniz, ancak bu çift ters eğik çizgiden kaçmayı içerir, bu da okumayı zorlaştırır.


Whoops. Sean negatif sayılarla ilgileniyor, bu yüzden bu bir gelişme.
sidereal

2
"-? [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();

Bu, ondalık sayıları tutan sayıları çıkarmak içindir.


Negatifleri işlemez
OneCricketeer

5

Kabul edilen yanıt rakamları algılar ancak biçimlendirilmiş sayıları, örneğin 2.000 veya ondalık sayıları (ör. 4.8) algılamaz. Böyle bir kullanım için -?\\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);

Çıktı: [4.8, 2,000]


1
@JulienS .: Katılmıyorum. Bu normal ifade, OP'nin istediğinden çok daha fazlasını yapar ve yanlış yapar. (En azından, ondalık kısım isteğe bağlı bir grupta olmalıdır, içindeki her şey gerekli ve açgözlü olmalıdır (?:\.\d+)?
Alan Moore

Ondalık kısım için kesinlikle bir puanınız var. Ancak biçimlendirilmiş sayılarla karşılaşmak çok yaygındır.
Julien

@AlanMoore SO'nun birçok ziyaretçisi, değişen benzerlik / farklılıklara sahip sorunları çözmek için herhangi / farklı yollar arıyor ve önerilerin gündeme getirilmesi yararlı oluyor. OP bile aşırı basite indirgenmiş olabilir.
Mugoma J. Okomba

4

rasyonel sayılar için şunu kullanın: (([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))


1
OP tam sayı dedi, gerçek sayı değil. Ayrıca noktalardan kaçmayı unuttunuz ve bu parantezlerin hiçbiri gerekli değil.
Alan Moore

3

Java 8 kullanarak şunları yapabilirsiniz:

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]

Eğer negatif sayılar yoksa, sen kurtulabilirsiniz replaceAll(ve kullanımda !s.isEmpty()içinde filterböyle düzgün bölünmüş şey sadece var olarak,) 2-34(bu da tamamen de regex ile ele alınabilir split, ancak oldukça karışık).

Arrays.streamOur döner String[]bir içine Stream<String>.

filter-bir sayının parçası olmayanların yanı sıra baştaki ve sondaki boş dizelerden de kurtulur .

mapToInt(Integer::parseInt).toArray()çağrıları parseInther birinde Stringbize bir vermek int[].


Alternatif olarak, Java 9'un aşağıdaki gibi bir şeye izin vermesi gereken bir Matcher.results yöntemi vardır :

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]

Haliyle, ne bunların büyük bir gelişme üzerinde sadece sonuçların üzerinde döngü olduğunu Pattern/ ' Matcherdiğer yanıtlar gösterildiği gibi, ancak önemli ölçüde kullanımı ile basitleştirilmiş daha karmaşık işlemlerle bu takip etmek istiyorsanız daha basit olmalı Canlı Yayınlar.


1

Bunu kullanarak tüm gerçek sayıları çıkarın.

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

1

Gerçek sayıları temsil eden kesir ve gruplama karakterleri diller arasında farklılık gösterebilir. Aynı gerçek sayı, dile bağlı olarak çok farklı şekillerde yazılabilir.

Almanca'da iki milyon numara

2,000,000.00

ve İngilizce olarak

2.000.000,00

Belirli bir dizeden gerçek sayıları dilden bağımsız bir şekilde tam olarak çıkarma yöntemi:

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

1

Bar1 veya aa1bb gibi kelimelerin içinde bulunan sayıları hariç tutmak istiyorsanız, normal ifadeye dayalı yanıtlardan herhangi birine kelime sınırları \ b ekleyin. Örneğin:

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

görüntüler:

2
12

1

Bir String'den sayıları ayıklamak için ASCII değerlerini kontrol etmenizi öneririm Diyelim ki myname12345 olarak bir girdi String'iniz var ve sadece 12345 sayılarını çıkarmak istiyorsanız bunu önce String'i Karakter Dizisine dönüştürerek ve ardından aşağıdaki sözde kodu kullanarak yapabilirsiniz.

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

sayılar çıkarıldıktan sonra onları bir diziye ekleyin

Bu yardımcı olur umarım


Bir Java dizesi, sayılan Unicode / UTF-16 kod birimleri dizisidir. UTF-16'nın tasarımında, ilk 128 karakter ASCII kodlamasıyla aynı değere (aynı boyutta değil) sahiptir; Bunun ötesinde, ASCII ile uğraştığınızı düşünmek hatalara yol açacaktır.
Tom Blodget

0

Bu ifadeyi en basit buldum

String[] extractednums = msg.split("\\\\D++");

-1
public static String extractNumberFromString(String number) {
    String num = number.replaceAll("[^0-9]+", " ");
    return num.replaceAll(" ", "");
}

dizeden yalnızca sayıları çıkarır

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.