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());
}
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.
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”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.
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
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]
pour les nombres rationnels, utilisez celui-ci: (([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))
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.
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;
}
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;
}
}
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
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
J'ai trouvé cette expression la plus simple
String[] extractednums = msg.split("\\\\D++");