如何在 javascript 中解析包含数字/浮点数文本的字符串

How to parse a string containing text for a number/float in javascript?

本文关键字:数字 浮点数 文本 字符串 包含 javascript      更新时间:2023-09-26

我正在尝试构建一个能够解析句子并返回数字的javascript函数。

这是我为下面的测试用例设置的 jsFiddle -

  1. "我有 1 磅" -> 1
  2. "我有 3.50 英镑要花" -> 3.50
  3. "我有 23.00 磅" -> 23
  4. '£27.33' -> 27.33
  5. '$4345.85' -> 4345.85
  6. '3.00' -> 3
  7. '7.0' -> 7
  8. "应该有2.0。" -> 2
  9. "应该有15.20。" -> 15.20
  10. '3.15' -> 3.15
  11. "我只有5个,不是很好>。">
  12. ' 34.23
  13. ' -> 34.23
  14. 'sdfg545.14sdfg' -> 545.14
  15. "昨天我花了235468.13英镑。今天我想少花钱。 -> 235468.13
  16. "昨天我度过了340磅" -> 340
  17. "我今天花了14.52英镑,明天花了17.30英镑" -> 14.52
  18. "我有0棵树,明天11.33英镑" -> 0

16&17表示它应该找到第一个数字。我知道有些测试用例可能很困难,但我欢迎任何能让我得到合理覆盖的东西。

这是我用于函数的格式

function parseSentenceForNumber(sentence){
    return number; //The number from the string
}

我想我自己可以完成 60-80% 的方法,但我希望正则表达式可能是这里最好的解决方案,而且我从来都不擅长它们。希望我有足够的测试用例,但请随时添加我可能错过的任何测试用例。

非常感谢

您的帮助

**更新**

大量的工作答案,我需要花一些时间更详细地查看它们。Mike Samuel 提到了逗号和 .5,这导致我添加了另外几个测试用例

18."我有1000磅"->100019.'.5' -> 0.5

jsalonen 提到添加没有数字的测试用例

20."这句话没有数字" ->空

这是使用 jsalonen 解决方案的更新小提琴,如果没有我的规格更改,我将 100% 在那里,更改我是 95%。任何人都可以提供带逗号的数字 18 的解决方案吗?

**更新**

我添加了一个语句来去除 jsalonen 函数的逗号,我是 100%。

这是最后一个函数

function parseSentenceForNumber(sentence){
    var matches = sentence.replace(/,/g, '').match(/('+|-)?(('d+('.'d+)?)|('.'d+))/);
    return matches && matches[0] || null;
}

最后的小提琴

非常感谢您的帮助,在此过程中我提高了我的正则表达式知识。谢谢

将所有负数和正数与任意位数匹配的答案:

function parseSentenceForNumber(sentence){
    var matches = sentence.match(/('+|-)?(('d+('.'d+)?)|('.'d+))/);
    return matches && matches[0] || null;
}

考虑添加负测试用例,例如测试当字符串没有数字时会发生什么:

test("Test parseSentenceForNumber('This sentence contains no numbers')", function() {
  equal( parseSentenceForNumber('This sentence contains no numbers'), null );
});

全提琴:http://jsfiddle.net/cvw8g/6/

正则表达式:

'd+(?:'.'d+)?

应该这样做。

  • 'd+匹配一系列数字。
  • .''d+ 匹配后跟数字的小数点。
  • (?:...)?使该组可选

这不处理分数全为零的特殊情况,并且您不希望分数包含在结果中,这对于正则表达式来说很困难(我不确定是否可以做到,尽管我愿意被证明是错误的(。将数字与其中的小数匹配后,应该更容易处理。

匹配字符串中的数字后,使用 parseFloat() 将其转换为数字,toFixed(2)获得 2 位小数。

计算机可读形式的数字的一般形式是:

/[+'-]?((?:[1-9]'d*|0)(?:'.'d*)?|'.'d+)([eE][+-]?'d+)?/

基于语法

number            := optional_sign (integer optional_fraction | fraction) optional_exponent;
optional_sign     := '+' | '0' | ε;
integer           := decimal_digit optional_integer;
optional_integer  := integer | ε;
optional_fraction := '.' optional_integer | ε;
fraction          := '.' integer;
optional_exponent := ('e' | 'E') optional_sign integer;

所以你可以做

function parseSentenceForNumber(sentence){
  var match = sentence.match(
      /[+'-]?((?:[1-9]'d*|0)(?:'.'d*)?|'.'d+)([eE][+-]?'d+)?/);
  return match ? +match[0] : null; //The number from the string
}

但这并不能解释

  1. 使用"."以外的分数分隔符的区域设置,如"π是 3,14159...">
  2. 逗号分隔数字组,如 1,000,000
  3. 分数
  4. 百分比
  5. 自然语言描述,如"一打"或"1500万英镑">

为了处理这些情况,您可以搜索"实体提取",因为这是尝试查找在非结构化文本中指定结构化数据的短语的总体字段。

另一个可能的正则表达式:

/'d+'.?'d{0,2}/

这意味着:

  • 'd:一个或多个数字
  • '.?:零个或一个周期
  • 最多 2 位数字d{0,2}

http://jsfiddle.net/cvw8g/7/

没有正则表达式,也使用解析(因此如果未找到数字,将返回 NaN(。
查找字符串中的第一个数字,然后尝试从该点分析它。

通过所有测试,并返回一个数字,而不是一个字符串,因此您可以立即将其用于比较或算术。

function parseSentenceForNumber(str) {
    //tacked on to support the new "1,000" -> 1000 case
    str = str.replace(',', '');
    var index;
    //find the first digit
    for (index = 0; index < str.length; ++index) {
        if (str.charAt(index) >= '0' && str.charAt(index) <= '9')
            break;
    }
    //checking for negative or decimal point (for '.5')
    if (index > 0 && (
        str.charAt(index - 1) == '-' ||
        str.charAt(index - 1) == '.'
    ))
        //go back one character
        --index;
    //get the rest of the string, accepted by native parseFloat
    return parseFloat(str.substring(index));
}

通过所有测试,我认为它的可读性要高得多:

function parseSentenceForNumber(sentence){
    return parseFloat(sentence.replace(/,(?='d)/g,"").match(/-?'.?'d.*/g));
}

。几乎所有测试:当句子中没有数字时,它返回"NaN"而不是"null"。但我认为"NaN"比简单的"null"信息量更大。

这是jsFiddle:http://jsfiddle.net/55AXf/