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

时间:2013-07-26 15:55:00

标签: javascript regex

我正在尝试构建一个能够解析句子并返回数字的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,不是很好。' - > 5
  12. '34.23' - > 34.23
  13. 'sdfg545.14sdfg' - > 545.14
  14. '昨天我花了235468.13英镑。 今天我想少花钱。 - > 235468.13
  15. '昨天我花了 340pounds“。 - > 340
  16. '我今天花了14.52英镑,明天花了17.30英镑' - > 14.52
  17. '我有0棵树,明天11.33英镑' - > 0
  18. 16& 17表示它应该找到第一个数字。我知道有些测试用例可能很难,但我欢迎任何能让我得到合理报道的测试用例。

    这是我用于我的功能的格式

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

    我想我自己可以得到60-80%的方式,但我希望正则表达式可能是最好的解决方案,而且我从来都不擅长。希望我有足够的测试用例,但随意添加我可能错过的任何一个。

    您的帮助非常赞赏。

    **更新**

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

    18.'我有1000磅' - > 1000 19。'。'5' - > 0.5

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

    20.'这句话不包含数字' - >空

    以下是使用jsalonen解决方案更新的fiddle,没有我的规格更改我会100%在那里,我的95%的变化。任何人都可以用逗号提供18号解决方案吗?

    **更新**

    我添加了一个声明来删除逗号到jsalonen的函数,我是100%。

    这是最后的功能

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

    最后Fiddle

    非常感谢帮助,并且我一直在改进我的正规表达知识。谢谢

6 个答案:

答案 0 :(得分:2)

正则表达式:

\d+(?:\.\d+)?

应该这样做。

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

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

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

答案 1 :(得分:2)

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

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/

答案 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万磅”
  6. 要处理这些情况,您可以搜索“实体提取”,因为这是尝试查找在非结构化文本中指定结构化数据的短语的首要字段。

答案 3 :(得分:1)

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

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

这意味着:

  • \d:一个或多个数字
  • \.?:零或一个句号
  • d{0,2}最多2位数

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

答案 4 :(得分:1)

没有正则表达式,也使用解析(如果没有找到数字,将返回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));
}

答案 5 :(得分:1)

通过所有测试,我认为它更具可读性:

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

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

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