有没有更好的选择来检查子字符串是不是为数字?

Posted

技术标签:

【中文标题】有没有更好的选择来检查子字符串是不是为数字?【英文标题】:Is there any better option for checkin if a substring is numeric?有没有更好的选择来检查子字符串是否为数字? 【发布时间】:2021-10-08 19:03:19 【问题描述】:

我正在尝试解析一个长字符串。在字符串中,有数字和其他种类的符号(文本)。我需要分别存储单词和数字。首先,我将字符串用空格分隔。

String fullString = "Some 3 random 5.6 text 12 with -4.5 numbers -1 in 0 beetween";
String [] words = fullString.split(" ");

我已经创建了一个方法来检查 Double.parseDouble() 方法是否在 words 变量中存储的每个子字符串上出现和异常。

private static boolean isNumeric(String str) 
    if (str == null) 
       return false;
    
    try 
       double parseDouble = Double.parseDouble(str);
     catch (NumberFormatException numberFormatException) 
       return false;
    
    return true;

在我的代码中,当我得到 true 时,我将不得不运行两次 Double.parseDouble(str) 方法。

for(String word: words)
    if(isNumeric(word))
        numbers.push = Double.parseDouble(word);
    

我想我正在寻找以下两个选项中的任何一个:

    一种更简单的方法来检查存储在words 中的子字符串是否为数字。 另一种只解析一次双精度的方法。

【问题讨论】:

您可以使用正则表达式删除单词然后拆分并知道其余的是数字 还有一个函数调用 isNaN,它将(不是数字)测试字符串是否是任何形式的数字,包括指数表达式和其他东西。如果字符串被认为是有效数字,它将返回 false。 也许尝试使用正则表达式。你的isNumeric() 实际上可以变成一个简单的word.matches("[\d]+") 您可以尝试 Apache Commons 库中的 NumberUtils。 baeldung.com/java-check-string-number 一个问题:除了数字和字母数字之外,您还有一些其他字符。你想用这些做什么? 【参考方案1】:

在您的情况下,如果使用 Double.parseDouble() 是一个足够好的指标,如果字符串是否为数字,并且您只想避免运行相同的方法两次,一次用于验证,一次用于实际解析,而不是使用 MgntUtils Open TextUtils 类中具有以下方法的源库:

public static double parseStringToDouble(java.lang.CharSequence num,
                                         double defaultValue)

你可以这样使用它:

Double num = TextUtils.parseStringToDouble(parsedStr, Double.MIN_VALUE);
if(Double.MIN_VALUE.equals(num)) 
  treatStringAsNotNumeric(parsedStr);
 else 
  treatStringAsNumeric(num /* or may be parsedStr*/);

该库以Maven artifact 和Github 的形式提供(包括源代码和Javadoc)。 Javadoc 也可以在线获取here

免责声明:库是我写的

【讨论】:

【参考方案2】:

关于字符串的问题在于,可以在字符串中以多种不同格式提供数值,其中一些格式永远不会被数字解析器(如Integer.parseInt()Double.parseDouble())传递。下面的 isNumeric() 方法可以处理相当多的最常见的方法,至少是在北美使用的方法。需要对String#matches() 方法中以下isNumeric() 方法代码中使用的Regular Expression 进行一些修改,以处理世界其他地区使用的其他特定数字符号格式。

isNumeric() 方法:

/**
 * Returns true if the string is a numerical type value.
 * 
 * The Regular Expression (regex) used here covers just about any provided 
 * numerical values like:<pre>
 * 
 *    "05", "0",   "18", "-12", "-33.0", "0.33", "-22.8", ".675E8", 
 *    "-.322", "44.343e6", "+453", "+94.234, 1,234.87, 32,043,001"
 * </pre>
 * 
 * @param numericalString (String)
 * 
 * @return (boolean)
 */
public static boolean isNumeric(String numericalString) 
    /* Utilization of the String#matches() method.
       The String#replace() method is used to remove commas in numbers.
       These commas should also be removed before parsing to a specific 
       numerical data type (wherever that might be in your code).                         */
    return numericalString.replace(",", "").matches("[-+]?(\\d+)?(\\.(\\d+)?((?i)E\\d+)?)?");

如何使用 isNumeric() 方法:

// The string to work against.
String fullString = "Some 3 random 5.6 text 12 with -4.5 numbers -1 "
                  + "in 0 between. These are added 05 0 18 -12 -33.0 0.33 "
                  + "-22.8 .675E8 -.322 44.343e6 +453 +94.234 1,234.87 "
                  + "32,043,001 as well!";
    
/* Split the contents of fullString based on one or more 
   whitespaces as delimiter. This takes care of any strings
   that may have double-spacing anywhere within it.      */
String [] words = fullString.split("\\s+");
    
/* Because we may never know how large any given string may 
   be, We use the List Interface or ArrayList object to 
   create a collection of both words and double numerical 
   values. Either of these object can grow dynamically (as
   can may other objects). Arrays can not grow dynamically.
   You can convert these Lists to Arrays later if you really 
   like.                                      */
List<String> wordsList = new ArrayList<>();
List<Double> numbersList = new ArrayList<>();
    
/* Iterate through the 'words' array and add alpha character
   words to the 'wordsList' list and numerical values (if any)
   to the 'numbersList' list. In this example all string number
   values will be converted to Double data type (also handles 
   Exponents).         */
for (String wordStrg : words) 
    if (isNumeric(wordStrg)) 
        // The String#replace() method id used to remove commas in numbers.
        numbersList.add(Double.parseDouble(wordStrg.replace(",", "")));
    
    else 
        wordsList.add(wordStrg);
    

    
// Show what is in the Lists:
System.out.println("The Words List:");
System.out.println(wordsList);
System.out.println();
System.out.println("The Numbers List (as Double):");
System.out.println(numbersList);
    
// ==============================================================
// If for some reason you want to convert the Lists 
// to arrays then you can do it this way:
String[] onlyWords = wordsList.toArray(new String[wordsList.size()]);
Double[] onlyNumbers = numbersList.toArray(new Double[numbersList.size()]);
    
// Display The Arrays:
System.out.println();
System.out.println("The Words Array:");
System.out.println(Arrays.toString(onlyWords));
System.out.println();
System.out.println("The Numbers Array (as Double):");
System.out.println(Arrays.toString(onlyNumbers));

【讨论】:

【参考方案3】:

假设你有 commons-lang3 你可以做;

扩展 -> 也匹配像 0xFF 0e0 0L 这样的数字

Arrays.stream(words).filter(NumberUtils::isCreatable).toArray()

简单版本 -> 匹配 0 -0 0.0 .0

Arrays.stream(words).filter(Pattern.compile("^-?(\\d+|(\\.\\d+)|(\\d+\\.\\d+))$").asPredicate()).toArray()

【讨论】:

以上是关于有没有更好的选择来检查子字符串是不是为数字?的主要内容,如果未能解决你的问题,请参考以下文章

给定一个数字,检查数字是不是形成一个加法方程?

如何在 Swift 2.0 中检查 UITextField 是不是为空白?有没有更好的方法来计算字符串? [复制]

根据字符或数字选择子字符串

如何通过引用传递子字符串?

匹配两个特定子字符串之一之前或之后的数字子字符串

判断一个字符串是不是为数字