5

私はこの問題を解決しようとしていました:

このカタでは、文字列を整数に変換したいと考えています。文字列は単純に数字を単語で表します。

例:

  • "1" => 1
  • "20" => 20
  • 「二百四十六」 => 246
  • 「七百八十三千九百十九」 => 783919

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

これを行うために、以下のコードを思いつきました。 あなたの便宜のためにjsfiddleで。

私が遭遇した問題は、「70 万」が 10700 になることです。

私は一日かけて周りを見回してこれを理解しようとしましたが、ただ立ち往生しています。プログラムが実行する手順は次のとおりです。

  • 文字列は「千百七」になります-良い
  • 最初のwhileループは「千」を見つけ、乗数を1000に設定します-良いです
  • 2 番目の while ループは「100」を検出しますが、mult.exec(a[0]) if ステートメントは null に解決されます。- くそ

したがって、乗数が 100000 になる代わりに、値が 100000 になり、間違った答えを得る運命にあります。

これをデバッグしようとしているときに、jsfiddle の while の 2 番目のループで使用される配列を作成しようとしました。そこでは機能し、null ではなく「100」と同等でした。なぜこれが起こるのか知っている人はいますか?

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

4 に答える 4

5

多分あなたは正規表現を必要としない

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;
}
于 2013-11-09T21:59:35.017 に答える
1

非常に興味深い問題です。100、100 万、10 億などの文字列が出現するときはいつでも、その数を掛ける前のすべて、または数そのものである可能性があることに注意することが非常に重要だと思います。百なら、これで終わりでもないのかもしれない。「10万」のように、後で別の数を掛ける必要があるかもしれません。

totalOfUnitsしたがって、合計の計算を、totalOfHundreds、およびの 3 つの変数に分割しますtotalOfMultitudes。次に、すべての数字を次のように順番に修正します。

  • 100 未満の数値が検出された場合は、それを追加します。totalOfUnits
  • 100 が検出された場合:
    • totalOfUnits == 0 の場合、100 を加算totalOfHundreds
    • > 0 の場合totalOfUnits、100 * 単位を追加して 0totalOfHundredsに設定しますtotalOfUnits
  • 別の群れに遭遇した場合:
    • == 0 かつ百 == 0 の場合totalOfUnits、多数自体を totalOfMultitudes に追加します
    • totalOfUnits> 0 または> 0 の場合totalOfHundreds、複数回 ( totalOfUnits+ totalOfHundreds) を totalOfMultitudesに追加し、totalOfUnitsおよびtotalOfHundredsを 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;
}
于 2013-11-09T23:19:31.523 に答える
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;
    }
}   

70 万の場合は機能しますが、その膨大な数の場合は失敗します。正確な解決策は見つかりませんでしたが、百がnumber配列にあり、multiplier配列がおそらく問題の原因であるという事実。

興味深い小さな問題。たぶん、この手がかりがあれば、残りを理解することができます.

于 2013-11-09T20:59:03.030 に答える
-1

これは答えではありませんが、現在のアルゴリズムで単語を解析する方法がわからないため、アプローチについて少しコメントしたいと思います。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
于 2013-11-09T21:46:04.967 に答える