web-gelistirme-sc.com

Bir dizgiyi virgül bin ayraçlı bir sayıya nasıl ayrıştırırım?

Bir string olarak 2,299.00 'a sahibim ve onu bir sayıya ayırmaya çalışıyorum. 2. değişkenle sonuçlanan parseFloat komutunu kullanmaya çalıştım. Sanırım virgül sorun; Sadece virgül kaldırmak?

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

54
user1540714

Evet, virgülleri kaldırın:

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

Virgüllerin kaldırılması potansiyel olarak tehlikelidir, çünkü yorumlarda diğerleri de belirtildiği gibi, çoğu yerel bir virgül kullanarak farklı bir şey (ondalık basamak gibi) anlamına gelir.

İpinizi nereden aldınız bilmiyorum ama dünyanın bazı yerlerinde "2,299.00" = 2.299

Intl nesnesi bu sorunu çözmenin güzel bir yolu olabilirdi, ancak bir şekilde spec'i yalnızca Intl.NumberFormat.format() API ve hiçbir parse karşılığı olmadan göndermeyi başardılar.

İçinde kültürel sayısal karakterleri olan bir dizgiyi, herhangi bir i18n aklı başında bir makinede tanınabilir bir numaraya ayrıştırmanın tek yolu, sayı dizelerini http: // cldr biçimindeki tüm olası biçimleme biçimlerini kapatmak için CLDR verilerini kullanan bir kütüphane kullanmaktır. unicode.org/

Şimdiye kadar karşılaştığım en iyi iki JS seçeneği:

47
David Meister

Rakam, ondalık nokta veya eksi işareti olmayan her şeyi kaldırın (-):

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);

Güncellenen keman

Bilimsel gösterimde sayılar için işe yaramayacağını unutmayın. İsterseniz, replace, e ve +'yi kabul edilebilir karakterler listesine eklemek için E satırını değiştirin:

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

Modern tarayıcılarda, dahili Intl.NumberFormat içinde tarayıcının sayı biçimini algılamak ve girişi eşleştirmek için normalleştirmek için kullanabilirsiniz.

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 }`);
}

Açıkçası bazı optimizasyon ve önbellekleme için yer var ama bu her dilde güvenilir bir şekilde çalışıyor.

20
Paul Alexander

Genellikle, sayısal değerler için serbest metin girişine izin vermeyen giriş alanlarını kullanmayı düşünmelisiniz. Ancak giriş biçimini tahmin etmeniz gerektiğinde durumlar olabilir. Örneğin, Almanya'da 1.234,56, ABD'de 1,234,56 anlamına gelir. Ondalık olarak virgül kullanan ülkelerin listesi için https://salesforce.stackexchange.com/a/21404 sayfasına bakın.

En iyi tahminde bulunmak ve sayısal olmayan tüm karakterleri çıkarmak için aşağıdaki işlevi kullanıyorum:

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);
}   

Burada deneyin: https://plnkr.co/edit/9p5Y6H?p=preview

Örnekler:

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

Fonksiyonun bir zayıf noktası vardır: 1.123 veya 1.123 varsa, formatı tahmin etmek mümkün değildir - çünkü yerel formata bağlı olarak, virgül veya binlerce ayırıcı olabilir. Bu özel durumda, işlev ayırıcıya binlerce ayırıcı olarak davranacak ve 1123'e dönecektir.

11
Gerfried

Bu, parseFloat işlevinin etrafındaki sade ve sade bir sarmalayıcıdır.

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
Adam Jagosz

Milyonlarca sayı varsa, bu yanıtların tümü başarısız olur.

3,456,789, 3456 yöntemiyle yerine basitçe dönerdi.

Sadece virgülleri kaldırmak için en doğru cevap olmalı.

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

Ya da sadece yazılı. 

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

Bir toLocaleString içermeleri şaşırtıcı ancak bir parse yöntemi içermiyor. En azından toLocaleString, argümanlar olmadan IE6 + 'da iyi desteklenir.

Bir i18n çözümü için şunu buldum:

İlk önce kullanıcının yerel ayar ondalık ayırıcısını algıla:

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

Ardından, Dize'de birden fazla ondalık ayırıcı varsa, sayıyı normalleştirin:

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

Son olarak, sayı veya ondalık ayırıcı olmayan herhangi bir şeyi kaldırın:

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

David Meister'ın yayınladığı problemden kaçınmak istiyorsanız ve ondalık basamakların sayısından eminseniz, tüm noktaları ve virgülleri değiştirip 100'e bölebilirsiniz, örneğin:

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

veya 3 ondalık iseniz varsa

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

ParseInt, parseFloat veya Number kullanmak istiyorsanız bu size kalmış. Ayrıca ondalık basamakların sayısını korumak istiyorsanız, .toFixed (...) işlevini kullanabilirsiniz.

0

Virgül boş bir dizeyle değiştirin: 

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

0
Aadit M Shah

Destekleyecek küçük bir yerel ayar kümeniz varsa, birkaç basit kuralı kodlayarak muhtemelen daha iyi olursunuz:

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

Bir l10n cevabı istiyorsanız, bu şekilde yapın. Örnek para birimi kullanır, ancak buna ihtiyacınız yoktur. Eski tarayıcıları desteklemeniz gerekirse, Intl kütüphanesinin çoklu doldurulması gerekir.

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, ""));
0
Tony Topper