如何从字符串中提取数字并获取整数数组?


109

我有一个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
数字是否用空格或其他字符包围?数字是如何格式化的,它们是十六进制,八进制,二进制,十进制?
Buhake Sindi'3

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

Answers:


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

...打印-212


-?匹配前导负号-可选。\ d匹配一个数字,但是我们需要\\\Java String中那样编写。因此,\ d +匹配1个或多个数字。


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

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

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

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

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

52

怎样使用replaceAlljava.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”之间的字符

4
您为什么要保留问号?此外,这种治疗-本身的数量,与顺水推舟一样9----61-2-3
艾伦·摩尔

1
不使用导入库的一个非常不错的选择;)
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

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


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

2
如果您使用“-?[0-9] +”,那么您也会处理负数
cegprakash13 2013年

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

这是为了提取保留小数的数字


不处理负面消息
OneCricketeer

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]


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

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

@AlanMoore许多SO的访问者正在寻找任何/不同的方式来解决具有相似/不同的问题,提出建议是有帮助的。甚至OP也可能过于简单化。
Mugoma J. Okomba,2016年

4

对于有理数,请使用以下一个: (([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))


1
OP表示整数,不是实数。另外,您忘记了转义点,并且不需要任何括号。
艾伦·摩尔

3

使用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(这也可以使用regex in来处理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如图所示其他的答案,但如果你想用更复杂的操作,这些操作与使用的显著简化跟进它应该是简单流。


1

以此提取所有实数。

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

表示实数的小数和分组字符在语言之间可能有所不同。取决于语言,可以用完全不同的方式来写相同的实数。

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

1

如果要排除单词中包含的数字(例如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

1

我建议检查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会导致错误。
汤姆·布洛杰特

0

我发现这个表达最简单

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

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

仅从字符串中提取数字

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.