Javascript将字符串解析为整数

时间:2013-11-09 20:41:24

标签: javascript

在代码大战中工作我试图解决这个问题:

在这个kata中我们想要将字符串转换为整数。字符串只代表单词中的数字。

示例:

  • “one”=> 1
  • “twenty”=> 20
  • “二百四十六”=> 246
  • “七八十三数千九百九十九”=> 783919

=============================================== ===================================

我想出了下面的代码来做到这一点。 On jsfiddle for you convience.

我遇到的问题是“七十万”给你10700。

我花了一天时间环顾四周,试图解决这个问题,但我只是陷入困境。该计划采取的步骤是:

  • 字符串变成'千零七' - 好
  • 首先while循环找到'千'并将乘数设置为1000 - 好
  • 第二个while循环找到'100',然后mult.exec(a [0])if语句解析为null。 - 该死的

因此,乘数不会变为100000,而是变为100000,我们注定要得到错误的答案。

在尝试调试时,我尝试在jsfiddle中创建在while中的第二个循环期间使用的数组。它在那里工作并等同于'百'而不是零。有人知道为什么会这样吗?

function parseInt(number) { 

    // reference array for english -> integer
    var ref = { one:1, two:2, three:3, four:4, five:5, six:6, seven:7, eight:8, nine:9, ten:10, eleven:11, twelve:12, thirteen:13, fourteen:14, fifteen:15, sixteen:16, seventeen:17, eighteen:18, nineteen:19, twenty:20, thirty: 30, forty: 40, fifty: 50, sixty: 60, seventy: 70, eighty: 80, ninety:90, hundred: 100, thousand: 1000, million: 1000000 };

    // regex to find number values from the string
    var find = new RegExp( "(one|t(wo|hree|en|welve|hirteen|wenty|hirty)|f(our|ive|ourteen|iftenn|orty|ifty)|s(ixteen|ixty|eventy|ix|even|eventeen|teen)|eigh(ty|t|teen)|nin(ety|e|eteen)|zero|hundred|thousand|million)", "gi" );

    // hundred/thousand/million etc. act as multipliers in this solution and need a seperate search
    var mult = new RegExp( "(hundred|thousand|million)", "gi" );

    // reversing the string allows us to add largest digits first
    number = number.split(' ').reverse().join(" ");

    // while there is a number in string number
    //   if that number is a multiplier
    //     if that number is 100 -> multiplier = multiplier * 100;
    //     else multiplier = reference value;
    //   else value = value + reference value * multiplier
    // end while
    value = 0; multiplier = 1;
    while( a = find.exec(number) ) {

        if( m = mult.exec(a[0]) ) {

            if( m[0] == 'hundred' ) { multiplier *= 100; }
            else { multiplier = ref[m[0]]; }

        }
        else {

            value += ref[a[0]] * multiplier;

        }

    }   
    return value;
}

4 个答案:

答案 0 :(得分:4)

也许你不需要正则表达式

function parse(numbersInString){
    var ref = { one:1, two:2, three:3, four:4, five:5, six:6, seven:7, eight:8, nine:9, ten:10, eleven:11, twelve:12, thirteen:13, fourteen:14, fifteen:15, sixteen:16, seventeen:17, eighteen:18, nineteen:19, twenty:20, thirty: 30, forty: 40, fifty: 50, sixty: 60, seventy: 70, eighty: 80, ninety:90 },
        mult = { hundred: 100, thousand: 1000, million: 1000000 },
        strNums = numbersInString.split(' ').reverse(),
        number = 0,
        multiplier = 1;

    for(i in strNums){
        if( mult[strNums[i]] != undefined ) {
            if(mult[strNums[i]]==100) {
                multiplier*=mult[strNums[i]]
            }else{
                multiplier=mult[strNums[i]]
            }
        } else {
            if (!isNaN(parseFloat(strNums[i]))) {
                number += parseFloat(strNums[i]) * multiplier;
            } else {
                var nums = strNums[i].split('-');
                number += ((ref[nums[0]]||0) + (ref[nums[1]]||0)) * multiplier;
            }
        }
    }
    return number;
}

答案 1 :(得分:1)

感觉mult.exec应该在while块中,以便将所有乘数放在一起。

这个小片段

while( a = find.exec(number) ) {
    if( m = mult.exec(a[0]) ) {
        while(m) {
            multiplier *= ref[m[0]];
            m = mult.exec(a[0]);
        }
    }
    else {
        value += ref[a[0]] * multiplier;
    }
}   

让事情为七十万工作,但随后为这个庞大的数字而破产。尽管我找不到确切的解决方案,但是number数组和multiplier数组中的数百可能是问题的根源。

有趣的小问题。也许有了这个线索,你可以得到其余的想法。

答案 2 :(得分:1)

非常有趣的问题。我认为非常重要的是观察到,当字符串中出现数百,数百万,等等时,它可能是它之前的所有数字,或数字本身。如果它是百,那可能是这甚至不是结束。我们可能不得不在之后成倍增加,比如“十万”。

因此,我将总计算分为3个变量:totalOfUnitstotalOfHundredstotalOfMultitudes。然后按顺序修改所有数字:

  • 如果遇到低于100的数字,请将其添加到totalOfUnits
  • 如果遇到100:
    • 如果totalOfUnit s == 0,请将100添加到totalOfHundreds
    • 如果totalOfUnits> 0,向totalOfHundreds添加100 *单位,并将totalOfUnits设为0
  • 如果遇到其他群众:
    • 如果totalOfUnits == 0且数百= = 0,请将众多本身添加到totalOfMultitudes
    • 如果totalOfUnits> 0或totalOfHundreds> 0,将多次(totalOfUnits + totalOfHundreds)添加到totalOfMultitudes并将totalOfUnitstotalOfHundreds设置为0。

最后,返回totalOfUnits + totalOfHundreds + totalOfMultitudes。代码适用于所有给定的示例,如下所示:

function parseNumber(num){
    var units = {
        zero:0, one:1, two:2, three:3, four:4, five:5, six:6, seven:7, eight:8, nine:9, ten:10,
        eleven:11, twelve:12, thirteen:13, fourteen:14, fifteen:15, sixteen:16, seventeen:17, eighteen:18, nineteen:19,
        twenty:20, thirty: 30, forty: 40, fifty: 50, sixty: 60, seventy: 70, eighty: 80, ninety:90
    };
    var hundreds = {
        hundred: 100
    };
    var multitudes = {
        hundred: 100,
        thousand: 1000,
        million: 1000000
    };

    var parts = num.split(/[ -]/);

    totalOfUnits = 0;
    totalOfHundreds = 0;
    totalOfMultitudes = 0;

    var result = undefined;

    for(var i = 0; i < parts.length; i++){
        if(units[parts[i]]){
            //Add unit
            totalOfUnits = totalOfUnits + units[parts[i]];
        }else if(hundreds[parts[i]]){
            totalOfHundreds += hundreds[parts[i]] * (totalOfUnits || 1);
            totalOfUnits = 0;
        }else if(multitudes[parts[i]]){
            totalOfMultitudes += multitudes[parts[i]] * (((totalOfUnits || 0) + (totalOfHundreds || 0)) || 1);
            totalOfUnits = totalOfHundreds = 0;
        }
    }

    return totalOfUnits + totalOfHundreds + totalOfMultitudes;
}

答案 3 :(得分:-1)

这不是一个答案,但我喜欢稍微评论一下这个方法,因为我看不出你怎么可能用你当前的算法解析这些单词。你可以让它适用于一个特定的实例或范围,但它永远不会适用于所有单词的变化。

如果您在数据结构中单独计算所有类型的单位,那将会更容易,也更容易预测,例如

var data = {
    millions:3, 
    hundredThousands:2,
    tenThousands:6, 
    thousands:6, 
    hundreds:0, 
    tens:8, 
    ones:9
};

在计数之后,您可以简单地将所有结果(包括零)串起来以构成整数值。

var value = [
        data.millions,
        data.hundredThousands,
        data.tenThousands,
        data.thousands,
        data.hundreds,
        data.tens,
        data.ones
    ].join('');

return parseInt(value); // 3266089