我有一个String变量(基本上是一个带有未指定数字数的英语句子),我想将所有数字提取到一个整数数组中。我想知道是否有一个使用正则表达式的快速解决方案?


我使用了Sean的解决方案并将其稍作更改:

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

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


评论

数字是否用空格或其他字符包围?数字是如何格式化的,它们是十六进制,八进制,二进制,十进制?

我认为问题很清楚:这是一个带有数字的英语句子。而且我在谈论整数数组,所以我要寻找的是整数。

#1 楼

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


...打印-212


-?匹配前导负号-可选。 \ d匹配一个数字,但是我们需要在Java字符串中将\写为\。因此,\ d +匹配1个或多个数字。

评论


您能通过解释正则表达式来补充您的答案吗?

– OscarRyz
2010年3月2日在22:42

-?匹配前导负号-可选。 \ d匹配一个数字,但是我们需要在Java字符串中将\写为\\。因此,\\ d +再匹配1个数字

– Sean Owen
10 Mar 2 '10在23:41



我将表达式更改为Pattern.compile(“-?[\\ d \\。] +”)以支持浮点数。您一定会带领我前进,Thx!

– jlengrand
2012年6月13日上午8:31

此方法检测数字,但不检测带格式的数字,例如2,000对于此类用途-?\\ d +,?\\ d + |-?\\ d +

– Mugoma J. Okomba
16 Mar 9 '16 at 12:25

那只支持一个逗号,所以会错过“ 2,000,000”。它还接受诸如“ 2,00”之类的字符串。如果必须支持逗号分隔符,则:-?\\ d +(,\\ d {3})*应该起作用。

– Sean Owen
16 Mar 9 '16 at 20:41

#2 楼

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


输出:

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



描述

[^-?0-9]+




[]将一组字符定为单个匹配的字符,即,以任何顺序仅一次匹配

^在集合的开头使用的特殊标识符,用于指示匹配定界集合中不存在的所有字符,而不是集合中存在的所有字符。

+在一次和无限次之间,尽可能地多次,根据需要进行回馈

-?字符“-”和“?”之一

0-9范围内的字符在“ 0”和“ 9”之间


评论


您为什么要保留问号?另外,它本身将数字与9-,-6和1-2-3等一起对待。

–艾伦·摩尔
16年5月18日在0:09

一个非常好的替代方法,而无需使用导入库;)

–萨那布里亚圣约翰教堂
17年2月2日在19:00

#3 楼

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


您实际上可以将\ [0-9]替换为\ d,但这涉及到双反斜杠转义,这使得阅读起来更加困难。

评论


哎呀肖恩(Sean)处理负数,因此是一种改进。

–恒星
10 Mar 2 '10在22:41

如果您使用“-?[0-9] +”,您的数字也会处理负数

–cegprakash
13-10-22在11:42

#4 楼

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


这是用于提取保留小数的数字

评论


不处理底片

– OneCricketeer
18年3月17日在17:32

#5 楼

接受的答案会检测到数字,但不会检测到格式化的数字,例如2,000,也不能为小数,例如4.8。对于此类用途-?\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);


输出:
[4.8, 2,000]

评论


@JulienS .:我不同意。这个正则表达式的作用远远超出了OP的要求,而且做错了。 (至少,小数部分应位于可选组中,所有内容都必须为贪婪的((:: \。\ d +)?.)。)

–艾伦·摩尔
16年5月18日在0:45

您肯定在那里有一个小数部分。但是,遇到格式化的数字是很常见的。

–朱利安
16年5月20日在6:58



@AlanMoore许多SO的访客都在寻找任何/不同的方式来解决相似/不同的问题,因此提出建议是有帮助的。甚至OP也可能过于简化。

– Mugoma J. Okomba
16年7月15日在0:43

#6 楼

对于有理数,请使用此数字:(([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))

评论


OP表示整数,而不是实数。此外,您忘记了转义点,并且不需要任何括号。

–艾伦·摩尔
2010年3月2日在23:01

#7 楼

使用Java 8,您可以执行以下操作:

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]


如果没有负数,则可以摆脱replaceAll(并在!s.isEmpty()中使用filter),如下所示:只是适当地分割了类似2-34的东西(也可以完全用split中的正则表达式来处理,但这相当复杂)。

Arrays.stream将我们的String[]变成了Stream<String>

filter删除了开头和结尾的空字符串以及所有不属于数字的-

mapToInt(Integer::parseInt).toArray()在每个parseInt上调用String来给我们一个int[]


或者,Java 9具有Matcher.results方法,该方法应允许以下内容:

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]



就目前而言,这两个方法都没有与其他答案中所示,相比仅用Pattern / Matcher循环结果,这是一个很大的改进,但是如果您想通过更复杂的操作跟进来,则应该更简单一些,使用流无法简化。

#8 楼

使用此提取所有实数。

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


#9 楼

表示实数的小数和分组字符在语言之间可能有所不同。根据语言,可以用不同的方式写出相同的实数。

200万的数字是德语的

2,000,000.00

和英语

2.000.000,00

一种以与语言无关的方式从给定字符串中完全提取实数的方法:

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


#10 楼

如果要排除单词中包含的数字(例如bar1或aa1bb),请在任何基于正则表达式的答案中添加单词边界\ b。例如:

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


显示器:

2
12


#11 楼

我建议检查ASCII值以从字符串中提取数字
假设您有一个输入字符串作为myname12345,并且如果您只想提取数字12345,则可以先将字符串转换为字符数组,然后使用下面的伪代码

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


一旦提取出数字,将其添加到数组中

希望对您有所帮助

评论


Java字符串是Unicode / UTF-16代码单元的序列。根据UTF-16的设计,前128个字符的值与ASCII编码的值相同(大小不同)。除此之外,以为您正在处理ASCII会导致错误。

–汤姆·布洛杰(Tom Blodget)
2014年5月26日在21:24

#12 楼

我发现此表达式最简单

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


#13 楼

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


仅从字符串中提取数字