web-dev-qa-db-fra.com

Comment extraire des nombres d'une chaîne et obtenir un tableau d'ints?

J'ai une variable String (essentiellement une phrase anglaise avec un nombre non spécifié de nombres) et j'aimerais extraire tous les nombres dans un tableau d'entiers. Je me demandais s'il y avait une solution rapide avec des expressions régulières?


J'ai utilisé la solution de Sean et l'ai légèrement modifiée:

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

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(line); 
while (m.find()) {
   numbers.add(m.group());
}
101
John Manak
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());
}

... imprime -2 et 12.


-? correspond à un signe négatif - facultatif.\d correspond à un chiffre et nous devons écrire \ comme \\ dans une chaîne Java bien que. Ainsi,\d + correspond à 1 ou plusieurs chiffres.

163
Sean Owen

Qu'en est-il d'utiliser la méthode replaceAll Java.lang.String:

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

Sortie:

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

Description

[^-?0-9]+
  • [ et ] délimitent un jeu de caractères à appariement unique, c'est-à-dire une seule fois dans n'importe quel ordre.
  • ^ Identifiant spécial utilisé au début de l'ensemble, utilisé pour indiquer la correspondance de tous les caractères non présents dans l'ensemble délimité, au lieu de tous les caractères présents dans l'ensemble.
  • + Entre une et plusieurs fois, autant de fois que possible, en rendant au besoin
  • -? Un des caractères “-” et “?”
  • 0-9 Un caractère compris entre “0” et “9”
47
Maxim Shoustin
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

Vous pouvez réellement remplacer [0-9] par\d, mais cela implique une double barre oblique inversée, ce qui rend la lecture plus difficile.

18
sidereal
  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();

Ceci est pour extraire des nombres en conservant la décimale

9
Kannan

La réponse acceptée détecte les chiffres mais ne détecte pas les nombres formatés, par ex. 2 000, ni décimales, p. Ex. 4.8 Pour une telle utilisation -?\\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);

Sortie: [4.8, 2,000]

5
Mugoma J. Okomba

pour les nombres rationnels, utilisez celui-ci: (([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))

4
Andrey

En utilisant Java 8, vous pouvez faire:

_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]
_

Si vous n'avez pas de nombre négatif, vous pouvez vous débarrasser de la replaceAll (et utiliser !s.isEmpty() dans filter), car cela ne sert qu'à diviser correctement quelque chose comme _2-34_ ( cela peut aussi être manipulé uniquement avec regex dans split, mais c'est assez compliqué).

_Arrays.stream_ transforme notre _String[]_ en un Stream<String> .

filter supprime les chaînes vides de début et de fin, ainsi que tout _-_ qui ne fait pas partie d'un nombre.

mapToInt(Integer::parseInt).toArray() appelle parseInt sur chaque String pour nous donner un _int[]_.


Sinon, Java 9 a une méthode Matcher.results , qui devrait permettre quelque chose comme:

_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]
_

En l'état actuel des choses, ni l'un ni l'autre ne constitue une amélioration importante par rapport aux résultats obtenus avec Pattern/Matcher comme indiqué dans les autres réponses, mais cela devrait être plus simple si vous souhaitez poursuivre avec ceci. opérations complexes qui sont considérablement simplifiées avec l'utilisation de flux.

3
Dukeling

Les fractions et les groupes de caractères représentant des nombres réels peuvent différer d'une langue à l'autre. Le même nombre réel peut être écrit de manières très différentes selon la langue.

Le nombre deux millions en allemand

2 000 000,

et en anglais

2.000.000,

Une méthode pour extraire complètement les nombres réels d'une chaîne donnée d'une manière agnostique:

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
AnDus

Extraire tous les nombres réels en utilisant ceci.

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
Swagger 68

Je suggérerais de vérifier les valeurs ASCII pour extraire les nombres d'une chaîne. Supposons que vous ayez un chaîne d'entrée sous la forme myname12345 et si vous voulez simplement extraire les nombres 12345 vous pouvez le faire en convertissant d’abord la chaîne en Character Array, puis utilisez le code suivant pseudocode

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

une fois que les nombres sont extraits, ajoutez-les à un tableau

J'espère que cela t'aides

1
The_Fresher

Si vous souhaitez exclure les nombres contenus dans des mots, tels que bar1 ou aa1bb, ajoutez des limites de mots\b à l'une des réponses basées sur les expressions rationnelles. Par exemple:

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

affiche:

2
12
1
dxl

J'ai trouvé cette expression la plus simple

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