カンマ千区切りの文字列を数値に解析するにはどうすればよいですか?


103

私は2,299.00文字列を持ち、それを数値に解析しようとしています。を使用してみましたがparseFloat、結果は2になりました。コンマが問題だと思いますが、この問題を正しい方法で解決するにはどうすればよいですか?カンマを削除しますか?

var x = parseFloat("2,299.00")
alert(x);

回答:


121

はい、コンマを削除します。

parseFloat(yournumber.replace(/,/g, ''));

7
ええ、でも小数点以下は失われました。たとえば、2300.00は2300になります。
user1540714 '26 / 07/26

@ user1540714これは、文字列ではなく浮動小数点であるためです。次に出力する必要がある場合は、常に小数点以下2桁を表示するようにフォーマットする必要があります。
ジョンテイラー

それは回避できますか?Ill tr​​y toFixed
user1540714

38
代わりに、以下を使用してすべてのコンマをキャプチャすることをお勧めします。.replace(/,/g, '') この正規表現はグローバルgを使用してすべてを置換します。
gdibble 2015

32
この回答がなぜ多くの賛成票を得て正解として選ばれたのか、私にはわかりません。2つの深刻な問題があります。1. parseFloat("2,000,000.00".replace(',',''))リターン2000など、複数のカンマを含む数値を処理できません。2. リターンなど,、小数点以下の多くの地域で失敗しparseFloat("2.000.000,00".replace(',',''))ます2
デビッドマイスター

113

他のコメントで述べられているように、多くのロケールはコンマを使用して別の意味(小数点以下の桁数など)を表すため、コンマを削除することは潜在的に危険です。

弦をどこから手に入れたのかはわかりませんが、世界のいくつかの場所では"2,299.00"=2.299

Intlオブジェクトは、この問題に取り組むための良い方法だったかもしれないが、何とか彼らだけでスペックを出荷するために管理Intl.NumberFormat.format()APIなしparseの相手:(

文化的な数字が含まれる文字列をi18nの正しい方法でマシンが認識できる数値に解析する唯一の方法は、CLDRデータを利用するライブラリを使用して、数値文字列http://cldr.unicodeをフォーマットするすべての可能な方法をカバーすることです。 org /

これまでにこれまでに出会った2つの最高のJSオプション:


4
まだ誰もこの回答に賛成していないとは言えません。このページでの唯一の実際の回答です!
evilkos 2017

9
Intlには対応する構文解析プログラムがあったはずであることに完全に同意します。人々がこれを必要とすることは明らかです。
ロスレス、2017

これはこれを行う唯一の体系的な方法です。これは、1つの正規表現当てはめアプローチでは実現できません。コンマとピリオドは、言語によって意味が異なります。
Wildhammer

38

最新のブラウザーでは、組み込みのIntl.NumberFormatを使用して、ブラウザーの数値フォーマットを検出し、一致するように入力を正規化できます。

function parseNumber(value, locale = navigator.language) {
  const example = Intl.NumberFormat(locale).format('1.1');
  const cleanPattern = new RegExp(`[^-+0-9${ example.charAt( 1 ) }]`, 'g');
  const cleaned = value.replace(cleanPattern, '');
  const normalized = cleaned.replace(example.charAt(1), '.');

  return parseFloat(normalized);
}

const corpus = {
  '1.123': {
    expected: 1.123,
    locale: 'en-US'
  },
  '1,123': {
    expected: 1123,
    locale: 'en-US'
  },
  '2.123': {
    expected: 2123,
    locale: 'fr-FR'
  },
  '2,123': {
    expected: 2.123,
    locale: 'fr-FR'
  },
}


for (const candidate in corpus) {
  const {
    locale,
    expected
  } = corpus[candidate];
  const parsed = parseNumber(candidate, locale);

  console.log(`${ candidate } in ${ corpus[ candidate ].locale } == ${ expected }? ${ parsed === expected }`);
}

それらは明らかにいくつかの最適化とキャッシングの余地がありますが、これはすべての言語で確実に機能します。


なぜこれは多くの賛成票を持っていないのですか!!! これは、国際的な形式のINPUTに対する最もエレガントなソリューションです。ありがとうございました!!
kpollock 2017

フランスの通貨は231 123 413,12です
stackdave

26

数字、小数点、またはマイナス記号(-)以外のものをすべて削除します。

var str = "2,299.00";
str = str.replace(/[^\d\.\-]/g, ""); // You might also include + if you want them to be able to type it
var num = parseFloat(str);

更新されたフィドル

科学表記の数値では機能しないことに注意してください。あなたがそれをしたい場合は、変更replace追加する行をeEと、+許容できる文字のリストに:

str = str.replace(/[^\d\.\-eE+]/g, "");

4
これは負の数や科学的表記の数では機能しません。
Aadit M Shah

1
str = str.replace(/(\d+),(?=\d{3}(\D|$))/g, "$1"); これは私が使用するものですが、私は正規表現ではまったく役に立たないので、他のSOスレッドでしばらく見つけたものです。
ジョンテイラー

@JonTaylor:ここでの目標は、数値を検証することではなく、それを機能させることだけparseFloatでした。:-)
TJクラウダー2012

私の知る限り、私が行うことはどれですか。私はこれを使用して、1,234,567などを1234567に変換します。私が言ったように、私は正規表現ではまったく役に立たないので、私の人生でそれが実際に何をしているのかを伝えることはできませんでした。
ジョンテイラー

1
"-"マイナス記号を削除するのは悪い考えです-完全に他の数値を取得します。また、異種形式を解析する場合は、 "7.500"!== "7,500"
Serge

14

通常、数値の自由なテキスト入力を許可しない入力フィールドの使用を検討する必要があります。ただし、入力形式を推測する必要がある場合もあります。たとえば、ドイツの1.234,56は米国の1,234.56を意味します。コンマを10進数として使用する国のリストについては、https://salesforce.stackexchange.com/a/21404を参照してください

次の関数を使用して、最善の推測を行い、すべての非数値文字を取り除きます。

function parseNumber(strg) {
    var strg = strg || "";
    var decimal = '.';
    strg = strg.replace(/[^0-9$.,]/g, '');
    if(strg.indexOf(',') > strg.indexOf('.')) decimal = ',';
    if((strg.match(new RegExp("\\" + decimal,"g")) || []).length > 1) decimal="";
    if (decimal != "" && (strg.length - strg.indexOf(decimal) - 1 == 3) && strg.indexOf("0" + decimal)!==0) decimal = "";
    strg = strg.replace(new RegExp("[^0-9$" + decimal + "]","g"), "");
    strg = strg.replace(',', '.');
    return parseFloat(strg);
}   

ここで試してください:https : //plnkr.co/edit/9p5Y6H?p=preview

例:

1.234,56  => 1234.56
1,234.56USD => 1234.56
1,234,567 => 1234567
1.234.567 => 1234567
1,234.567 => 1234.567
1.234 => 1234 // might be wrong - best guess
1,234 => 1234 // might be wrong - best guess
1.2345 => 1.2345
0,123 => 0.123

この関数には1つの弱点があります。1,123または1.123がある場合、形式を推測することはできません。ロケールの形式によっては、両方ともカンマまたは桁区切りの場合があるためです。この特殊なケースでは、関数は区切り記号を千単位の区切り記号として扱い、1123を返します。


1,111.11のような数字では失敗します。これは明らかに英語形式ですが、111111を返します
Goferito氏

ゴフェリートさん、ありがとうございました-すみません-機能を修正しました。
ゲルフリート

これは、たとえばフランスのロケールで非常に小さい数値 "0,124"の場合も失敗する可能性があるようです。
ポールアレクサンダー

すごい!これはほぼ正確に、私が探していたものです:3,00 €3.00にも置き換えられます。ただのメモです。これ3,001はにフォーマットされてい3001ます。これを回避するには、入力に常に小数点記号を使用する必要があります。たとえば、3,001.00€ 3,001.00正しく変換されます。また、jsfiddleを更新してください。0,124まだ124に変換されています
Arnis Juraga 2017年

よくやったバディ私はその価値が正解だと思います
Waheed

5

toLocaleStringが含まれていて、解析メソッドが含まれていないのは困惑しています。少なくとも引数なしのtoLocaleStringは、IE6 +で十分にサポートされています。

以下のために国際化ソリューション、私はこの思い付きました:

まず、ユーザーのロケールの小数点記号を検出します。

var decimalSeparator = 1.1;
decimalSeparator = decimalSeparator.toLocaleString().substring(1, 2);

次に、文字列に複数の小数点記号がある場合は数値を正規化します。

var pattern = "([" + decimalSeparator + "])(?=.*\\1)";separator
var formatted = valor.replace(new RegExp(pattern, "g"), "");

最後に、数値または小数点記号以外のものをすべて削除します。

formatted = formatted.replace(new RegExp("[^0-9" + decimalSeparator + "]", "g"), '');
return Number(formatted.replace(decimalSeparator, "."));

5

これは、parseFloat関数の単純化された控えめなラッパーです。

function parseLocaleNumber(str) {
  // Detect the user's locale decimal separator:
  var decimalSeparator = (1.1).toLocaleString().substring(1, 2);
  // Detect the user's locale thousand separator:
  var thousandSeparator = (1000).toLocaleString().substring(1, 2);
  // In case there are locales that don't use a thousand separator
  if (thousandSeparator.match(/\d/))
    thousandSeparator = '';

  str = str
    .replace(new RegExp(thousandSeparator, 'g'), '')
    .replace(new RegExp(decimalSeparator), '.')

  return parseFloat(str);
}

2

David Meisterが投稿した問題を回避したい場合で、小数点以下の桁数がわかっている場合は、すべてのドットとコンマを置き換えて100で除算できます。例:

var value = "2,299.00";
var amount = parseFloat(value.replace(/"|\,|\./g, ''))/100;

または、小数点以下3桁の場合

var value = "2,299.001";
var amount = parseFloat(value.replace(/"|\,|\./g, ''))/1000;

parseInt、parseFloat、またはNumberを使用するかどうかは、あなた次第です。また、小数点以下の桁数を保持したい場合は、関数.toFixed(...)を使用できます。


1

数百万の数がある場合、これらの答えはすべて失敗します。

3,456,789は単にreplaceメソッドで3456を返します。

単にカンマを削除するための最も正しい答えはでなければなりません。

var number = '3,456,789.12';
number.split(',').join('');
/* number now equips 3456789.12 */
parseFloat(number);

または単に書かれました。

number = parseFloat(number.split(',').join(''));

もちろん、アメリカンではドットではなくコンマを使用しています。両方を処理しようとして怪物を作ろうとするのはばかげたことでしょう。
ケース

2
しかし、そのような「怪物」は、Unicodeが提供するものの一部としてすでに存在しています(私の回答を参照してください)。あなたが海外の顧客と一緒に会社を経営しているなら、あなたはこれについて愚かさを感じなくなると確信しています。
David Meister

1

これにより、どのロケールの数値も通常の数値に変換されます。小数点にも有効:

function numberFromLocaleString(stringValue, locale){
    var parts = Number(1111.11).toLocaleString(locale).replace(/\d+/g,'').split('');
    if (stringValue === null)
        return null;
    if (parts.length==1) {
        parts.unshift('');
    }   
    return Number(String(stringValue).replace(new RegExp(parts[0].replace(/\s/g,' '),'g'), '').replace(parts[1],"."));
}
//Use default browser locale
numberFromLocaleString("1,223,333.567") //1223333.567

//Use specific locale
numberFromLocaleString("1 223 333,567", "ru") //1223333.567

1

この機能を使用すると、のような複数の形式で値をフォーマットすることができるようになります1.234,561,234.56、とさえ持つようなエラー1.234.561,234,56

/**
 * @param {string} value: value to convert
 * @param {bool} coerce: force float return or NaN
 */
function parseFloatFromString(value, coerce) {
    value = String(value).trim();

    if ('' === value) {
        return value;
    }

    // check if the string can be converted to float as-is
    var parsed = parseFloat(value);
    if (String(parsed) === value) {
        return fixDecimals(parsed, 2);
    }

    // replace arabic numbers by latin
    value = value
    // arabic
    .replace(/[\u0660-\u0669]/g, function(d) {
        return d.charCodeAt(0) - 1632;
    })

    // persian
    .replace(/[\u06F0-\u06F9]/g, function(d) {
        return d.charCodeAt(0) - 1776;
    });

    // remove all non-digit characters
    var split = value.split(/[^\dE-]+/);

    if (1 === split.length) {
        // there's no decimal part
        return fixDecimals(parseFloat(value), 2);
    }

    for (var i = 0; i < split.length; i++) {
        if ('' === split[i]) {
            return coerce ? fixDecimals(parseFloat(0), 2) : NaN;
        }
    }

    // use the last part as decimal
    var decimal = split.pop();

    // reconstruct the number using dot as decimal separator
    return fixDecimals(parseFloat(split.join('') +  '.' + decimal), 2);
}

function fixDecimals(num, precision) {
    return (Math.floor(num * 100) / 100).toFixed(precision);
}
parseFloatFromString('1.234,56')
"1234.56"
parseFloatFromString('1,234.56')
"1234.56"
parseFloatFromString('1.234.56')
"1234.56"
parseFloatFromString('1,234,56')
"1234.56"

0

l10nの回答が必要な場合は、このようにしてください。例では通貨を使用していますが、通貨は必要ありません。古いブラウザをサポートする必要がある場合は、Intlライブラリをポリフィルする必要があります。

var value = "2,299.00";
var currencyId = "USD";
var nf = new Intl.NumberFormat(undefined, {style:'currency', currency: currencyId, minimumFractionDigits: 2});

value = nf.format(value.replace(/,/g, ""));

9
一部のロケール(DEなど)ではコンマが小数点であるため、これは実際にはl10nの回答ではありません。
Andreas

また、with フラグreplace()を使用RegExpしない場合は、最初の一致のみを置き換え'g'ます。
binki 2017年

@binkiありがとうございます。修繕。
トニートッパー2017

@Andreasこれはl10nの答えです。別の通貨が必要な場合は、currencyIdの値をその国のcurrencyIdに変更するだけです。
トニートッパー2017

1
@TonyTopperこれは、桁区切り記号の置換がハードコードされ,ているという事実を変更しません。これは、一部のロケールではコンマ区切りです
Andreas

0

コンマを空の文字列に置き換えます。

var x = parseFloat("2,299.00".replace(",",""))
alert(x);


これは安全ではありません。他の回答で述べたように、世界の多くの場所で、カンマは小数点を表します。
デビッドマイスター

1
また、この方法は、最初のカンマを置き換えるだけなので、2,299,000.00では機能しません
wizulus

0

サポートするロケールのセットが少ない場合は、いくつかの単純なルールをハードコーディングするだけで、おそらく良い結果が得られます。

function parseNumber(str, locale) {
  let radix = ',';
  if (locale.match(/(en|th)([-_].+)?/)) {
    radix = '.';
  }
  return Number(str
    .replace(new RegExp('[^\\d\\' + radix + ']', 'g'), '')
    .replace(radix, '.'));
}

0
const parseLocaleNumber = strNum => {
    const decSep = (1.1).toLocaleString().substring(1, 2);
    const formatted = strNum
        .replace(new RegExp(`([${decSep}])(?=.*\\1)`, 'g'), '')
        .replace(new RegExp(`[^0-9${decSep}]`, 'g'), '');
    return Number(formatted.replace(decSep, '.'));
};

0
Number("2,299.00".split(',').join(''));   // 2299

split関数は、区切り文字として「、」を使用して文字列を配列に分割し、配列を返します。
join関数は、split関数から返された配列の要素を結合します。
Number()関数は、結合された文字列を数値に変換します。


ソリューションとは何か、どのように問題を解決するかについてもう少し詳しく説明してください。
タリク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.