【问题标题】:How to extract numbers from a string and get an array of ints?如何从字符串中提取数字并获取整数数组?
【发布时间】:2011-01-22 23:14:11
【问题描述】:

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


我使用了肖恩的解决方案,稍作改动:

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

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

【问题讨论】:

  • 数字是否被空格或其他字符包围?数字是如何格式化的,它们是十六进制、八进制、二进制还是十进制?
  • 我认为从问题中很清楚:这是一个带数字的英文句子。此外,我说的是整数数组,所以我要寻找的是整数。

标签: java arrays regex string


【解决方案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 个或多个数字。

【讨论】:

  • 您能否通过解释您的正则表达式来补充您的答案?
  • -?匹配前导负号 - 可选。 \d 匹配一个数字,但我们需要在 Java 字符串中将 \ 写为 \\。所以,\\d+ 匹配多 1 个数字
  • 我将表达式更改为 Pattern.compile("-?[\\d\\.]+") 以支持浮点数。你肯定带我上路,谢谢!
  • 此方法检测数字但不检测格式化数字,例如2,000。对于这样的使用-?\\d+,?\\d+|-?\\d+
  • 那只支持一个逗号,所以会错过“2,000,000”。它还接受像“2,00”这样的字符串。如果必须支持逗号分隔符,那么:-?\\d+(,\\d{3})* 应该可以工作。
【解决方案2】:

怎么用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”之间的字符

【讨论】:

  • 为什么要保留问号?此外,这会将- 本身视为一个数字,以及9----61-2-3 之类的东西。
  • 不使用导入库的非常好的替代方案;)
【解决方案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,但这涉及到双反斜杠转义,这使得它更难阅读。

【讨论】:

  • 哎呀。肖恩处理负数,所以这是一个改进。
  • 如果你使用“-?[0-9]+”,你的也会处理负数
【解决方案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();

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

【讨论】:

  • 不处理底片
【解决方案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+)?。)
  • 小数部分肯定有道理。但是,遇到格式化数字是很常见的。
  • @AlanMoore SO 的许多访问者正在寻找任何/不同的方法来解决具有不同相似性/差异的问题,提出建议很有帮助。甚至 OP 也可能过于简单化了。
【解决方案6】:

对于有理数使用这个:(([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))

【讨论】:

  • OP 说的是整数,而不是实数。此外,您忘记了转义点,这些括号都不是必需的。
【解决方案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(并在filter中使用!s.isEmpty()),因为这只是为了正确拆分2-34之类的东西(这也可以处理纯粹使用split 中的正则表达式,但它相当复杂)。

Arrays.stream 将我们的String[] 变成Stream&lt;String&gt;

filter 去掉了前导和尾随的空字符串以及任何不属于数字的-

mapToInt(Integer::parseInt).toArray() 在每个String 上调用parseInt 给我们一个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】:

      用于表示实数的分数和分组字符可能因语言而异。同一个实数可以用不同的方式书写,具体取决于语言。

      德语中的两百万

      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 会导致错误。
          【解决方案12】:

          我发现这个表达式最简单

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

          【讨论】:

            【解决方案13】:
            public static String extractNumberFromString(String number) {
                String num = number.replaceAll("[^0-9]+", " ");
                return num.replaceAll(" ", "");
            }
            

            只从字符串中提取数字

            【讨论】:

              猜你喜欢
              • 2020-07-06
              • 2017-07-07
              • 2019-03-09
              • 2020-10-25
              • 2020-02-26
              • 2020-07-20
              相关资源
              最近更新 更多