Jak wydrukować liczbę z przecinkami jako tysiące separatorów w JavaScript

1780

Próbuję wydrukować liczbę całkowitą w JavaScript z przecinkami jako tysiące separatorów. Na przykład chcę pokazać liczbę 1234567 jako „1 234 567”. Jak miałbym to zrobić?

Oto jak to robię:

function numberWithCommas(x) {
    x = x.toString();
    var pattern = /(-?\d+)(\d{3})/;
    while (pattern.test(x))
        x = x.replace(pattern, "$1,$2");
    return x;
}

Czy istnieje prostszy lub bardziej elegancki sposób na zrobienie tego? Byłoby miło, gdyby działał również z pływakami, ale nie jest to konieczne. Aby wybierać między kropkami a przecinkami, nie musi być zależny od ustawień regionalnych.

Elias Zamaria
źródło
156
Number (x) .toLocaleString ()
Boffin
@Boffin to nie działa dla numeru typu wejścia (z powodu przecinków) - w przyjętej odpowiedzi możemy zamienić przecinek na kropkę, a numer typu wejścia będzie działał
Witalij Zdanevich
48
Warto zauważyć, że Number.prototype.toLocaleString nadal nie działa w Safari w 2016 roku . Zamiast faktycznie formatować liczbę, po prostu ją zwraca, bez zgłaszania błędu. Posiadanie największego facepalmu w wyniku tego ... #goodworkApple
aendrew
Wygląda jednak na to, że działa w Safari na iOS.
Tim
toLocaleString jest niespójny i nie należy go używać. Na przykład - w przeglądarce Firefox zwróci 1 234, ale w IE doda dziesiętne: 1 234,00
Bort

Odpowiedzi:

2831

Wykorzystałem pomysł z odpowiedzi Kerry, ale uprościłem go, ponieważ szukałem czegoś prostego do mojego konkretnego celu. Oto co zrobiłem:

function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}


Wyrażenie regularne używa 2 asercji:

  • dodatni, aby wyszukać dowolny punkt w ciągu, który ma wielokrotność 3 cyfr w rzędzie po nim,
  • twierdzenie negatywne, aby upewnić się, że punkt ma tylko wielokrotność 3 cyfr. Wyrażenie zastępujące umieszcza tam przecinek.

Na przykład, jeśli go zdasz 123456789.01, asercja dodatnia będzie pasować do każdego miejsca po lewej stronie 7 (ponieważ 789jest wielokrotnością 3 cyfr, 678jest wielokrotnością 3 cyfr 567itp.). Twierdzenie negatywne sprawdza, czy wielokrotność 3 cyfr nie ma po nim żadnych cyfr. 789ma kropkę po nim, więc jest dokładnie wielokrotnością 3 cyfr, więc przecinek tam. 678jest wielokrotnością 3 cyfr, ale ma 9po nim, więc te 3 cyfry są częścią grupy 4, a przecinek tam nie występuje. Podobnie dla 567. 456789ma 6 cyfr, co jest wielokrotnością 3, więc przecinek poprzedza. 345678jest wielokrotnością 3, ale ma 9po nim, więc nie ma tam przecinka. I tak dalej. The\B powstrzymuje wyrażenie regularne przed wstawieniem przecinka na początku łańcucha.

@ neu-rah wspomniał, że ta funkcja dodaje przecinki w niepożądanych miejscach, jeśli po przecinku są więcej niż 3 cyfry. Jeśli jest to problem, możesz użyć tej funkcji:

function numberWithCommas(x) {
    var parts = x.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return parts.join(".");
}

@ tjcrowder zwrócił uwagę, że teraz, gdy JavaScript ma lookbehind ( informacje o pomocy technicznej ), można go rozwiązać w samym wyrażeniu regularnym:

function numberWithCommas(x) {
    return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
}

(?<!\.\d*)jest negatywnym wyglądem, który mówi, że dopasowanie nie może być poprzedzone .przez zero lub więcej cyfr. Negatywne spojrzenie jest szybsze niż rozwiązanie spliti join( porównanie ), przynajmniej w V8.

Elias Zamaria
źródło
21
Bardzo fajnie, zauważyłem, że ma problemy z liczbami, które mają więcej niż 3 miejsca po przecinku.
Eric Petroelje
60
spróbuj numerWithCommas (12345.6789) -> „12 345,6,789” nie podoba mi się to
neu-rah
4
Nie działa dobrze z ułamkami, nie chcemy przecinków po przecinku
Mugen
30
Małe ulepszenie, które naprawiono po „.” problem '123456789.01234' .replace (/ \ B (? = (? = \ d * \.) (\ d {3}) + (?! \ d)) / g, '_')
Dmitrij Golubev
8
@DmitrijGolubev Nie działa dla liczb całkowitych. Być może rozwiązaniem byłoby wymuszenie kropki dziesiętnej.
Vlad
1808

Dziwi mnie, że nikt nie wspominał o Number.prototype.toLocaleString . Jest zaimplementowany w JavaScript 1.5 (który został wprowadzony w 1999 roku), więc jest zasadniczo obsługiwany we wszystkich głównych przeglądarkach.

var n = 34523453.345
n.toLocaleString()
"34,523,453.345"

Działa również w Node.js od v0.12 poprzez włączenie Intl

Zwróć uwagę, że ta funkcja zwraca ciąg, a nie liczbę.

Jeśli chcesz czegoś innego, Numeral.js może być interesujący.

uKolka
źródło
17
@csigrist Dobre punkty, ale nie jest tak źle, jak się wydaje. Szybkość zależy od przeglądarki. W FF lub Operze działa dobrze. Jestem do bani w Chrome. Co do zer: var number = 123456.000; number.toLocaleString('en-US', {minimumFractionDigits: 2}); "123,456.00"te opcje nie działają jednak w FF i Safari.
uKolka
22
Różnica wydajności może, ale nie musi stanowić problemu, w zależności od kontekstu. Jeśli zostanie zastosowany do gigantycznej tabeli zawierającej 1000 wyników, będzie to ważniejsze, ale jeśli zastosuje się go tylko do pojedynczej wartości, różnica jest znikoma. Ale zaletą jest to, że jest on zależny od lokalizacji, więc ktoś w Europie zobaczy 34.523.453345 lub 34 523 453.345 . Byłoby to ważniejsze na stronie z odwiedzającymi z wielu krajów.
T Nguyen,
6
Niesamowite. Wreszcie odpowiedź z natywną funkcją. Co więcej, ten wyświetla się poprawnie w różnych krajach z różnymi separatorami (w Czechach piszemy X XXX XXX,YYY).
Tomáš Zato - Przywróć Monikę
22
Aktualizacja dla googlerów: toLocaleStringdziała w Node.js od v0.12 poprzez włączenie Intl .
srobinson
8
@MSC powinieneś spróbować parseInt("1234567", 10).toLocaleString('en-US', {minimumFractionDigits: 2})lub new Number("1234567").toLocaleString('en-US', {minimumFractionDigits: 2})zamiast tego. To nie działa, ponieważ używasz go na łańcuchu, a nie na liczbie.
uKolka
244
var number = 1234567890; // Example number to be converted

⚠ umysł że JavaScript ma maksymalną całkowitą wartość 9007199254740991


toLocaleString :

number.toLocaleString(); // "1,234,567,890"

// A more complex example: 
var number2 = 1234.56789; // floating point example
number2.toLocaleString(undefined, {maximumFractionDigits:2}) // "1,234.57"


NumberFormat ( Safari nie jest obsługiwane):

var nf = new Intl.NumberFormat();
nf.format(number); // "1,234,567,890"

Z tego, co sprawdziłem (przynajmniej Firefox), oba są mniej więcej takie same pod względem wydajności.

vsync
źródło
6
NumberFormat nie jest obsługiwany w Safari, dla każdego, kto tam wdraża.
marcovega,
6
toLocaleString nie jest również obsługiwane w safari
Deepak Banka
3
Obsługa przeglądarek jest zawsze wymieniona na dole każdej strony MDN, z którą mam łącze.
vsync
5
podstawowe toLocaleStringprace na safari, opcje nie
dandavis
3
toLocaleStringrozwiązanie powinno prawdopodobnie także pożądany lokum, tak toLocaleString("en"), ponieważ Anglicy używają wzór przecinków. Jeśli jednak toLocaleString()we Francji nie zostanie uruchomiony wskaźnik ustawień regionalnych, wówczas zamiast przecinków będą pojawiać się kropki, ponieważ używa się tego do lokalnego oddzielenia tysięcy.
Mike 'Pomax' Kamermans
112

Sugeruję użycie phpjs.org ' number_format ()

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // +    revised by: Luke Smith (http://lucassmith.name)
    // +     bugfix by: Diogo Resende
    // +     bugfix by: Rival
    // +      input by: Kheang Hok Chin (http://www.distantia.ca/)
    // +   improved by: davook
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Jay Klehr
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Amir Habibi (http://www.residence-mixte.com/)
    // +     bugfix by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Drew Noakes
    // *     example 1: number_format(1234.56);
    // *     returns 1: '1,235'
    // *     example 2: number_format(1234.56, 2, ',', ' ');
    // *     returns 2: '1 234,56'
    // *     example 3: number_format(1234.5678, 2, '.', '');
    // *     returns 3: '1234.57'
    // *     example 4: number_format(67, 2, ',', '.');
    // *     returns 4: '67,00'
    // *     example 5: number_format(1000);
    // *     returns 5: '1,000'
    // *     example 6: number_format(67.311, 2);
    // *     returns 6: '67.31'
    // *     example 7: number_format(1000.55, 1);
    // *     returns 7: '1,000.6'
    // *     example 8: number_format(67000, 5, ',', '.');
    // *     returns 8: '67.000,00000'
    // *     example 9: number_format(0.9, 0);
    // *     returns 9: '1'
    // *    example 10: number_format('1.20', 2);
    // *    returns 10: '1.20'
    // *    example 11: number_format('1.20', 4);
    // *    returns 11: '1.2000'
    // *    example 12: number_format('1.2000', 3);
    // *    returns 12: '1.200'
    var n = !isFinite(+number) ? 0 : +number, 
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
}

AKTUALIZACJA 02/13/14

Ludzie zgłaszali, że to nie działa zgodnie z oczekiwaniami, więc zrobiłem JS Fiddle, który zawiera automatyczne testy.

Aktualizacja 26.11.2017

Oto skrzypce jako fragment kodu z nieznacznie zmodyfikowanymi danymi wyjściowymi:

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // +    revised by: Luke Smith (http://lucassmith.name)
    // +     bugfix by: Diogo Resende
    // +     bugfix by: Rival
    // +      input by: Kheang Hok Chin (http://www.distantia.ca/)
    // +   improved by: davook
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Jay Klehr
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Amir Habibi (http://www.residence-mixte.com/)
    // +     bugfix by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +   improved by: Drew Noakes
    // *     example 1: number_format(1234.56);
    // *     returns 1: '1,235'
    // *     example 2: number_format(1234.56, 2, ',', ' ');
    // *     returns 2: '1 234,56'
    // *     example 3: number_format(1234.5678, 2, '.', '');
    // *     returns 3: '1234.57'
    // *     example 4: number_format(67, 2, ',', '.');
    // *     returns 4: '67,00'
    // *     example 5: number_format(1000);
    // *     returns 5: '1,000'
    // *     example 6: number_format(67.311, 2);
    // *     returns 6: '67.31'
    // *     example 7: number_format(1000.55, 1);
    // *     returns 7: '1,000.6'
    // *     example 8: number_format(67000, 5, ',', '.');
    // *     returns 8: '67.000,00000'
    // *     example 9: number_format(0.9, 0);
    // *     returns 9: '1'
    // *    example 10: number_format('1.20', 2);
    // *    returns 10: '1.20'
    // *    example 11: number_format('1.20', 4);
    // *    returns 11: '1.2000'
    // *    example 12: number_format('1.2000', 3);
    // *    returns 12: '1.200'
    var n = !isFinite(+number) ? 0 : +number, 
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().split('.');
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');
    }
    return s.join(dec);
}

var exampleNumber = 1;
function test(expected, number, decimals, dec_point, thousands_sep)
{
    var actual = number_format(number, decimals, dec_point, thousands_sep);
    console.log(
        'Test case ' + exampleNumber + ': ' +
        '(decimals: ' + (typeof decimals === 'undefined' ? '(default)' : decimals) +
        ', dec_point: "' + (typeof dec_point === 'undefined' ? '(default)' : dec_point) + '"' +
        ', thousands_sep: "' + (typeof thousands_sep === 'undefined' ? '(default)' : thousands_sep) + '")'
    );
    console.log('  => ' + (actual === expected ? 'Passed' : 'FAILED') + ', got "' + actual + '", expected "' + expected + '".');
    exampleNumber++;
}

test('1,235',    1234.56);
test('1 234,56', 1234.56, 2, ',', ' ');
test('1234.57',  1234.5678, 2, '.', '');
test('67,00',    67, 2, ',', '.');
test('1,000',    1000);
test('67.31',    67.311, 2);
test('1,000.6',  1000.55, 1);
test('67.000,00000', 67000, 5, ',', '.');
test('1',        0.9, 0);
test('1.20',     '1.20', 2);
test('1.2000',   '1.20', 4);
test('1.200',    '1.2000', 3);
.as-console-wrapper {
  max-height: 100% !important;
}

Kerry Jones
źródło
Nie, że to zaznaczyłem, ale wierzę, że ludzie to zrobili, ponieważ to nie działa. W tej chwili nawet niektóre z twoich testów nie działają.
Andrew S
3
@Andrew S - zaznaczyła to tylko 1 osoba. Działa, użyłem go wiele razy w swoim własnym kodzie. To także nie jest mój kod (ani moje testy), odwoływałem się do strony, z której pochodzi, czyli strony znanej. Być może mają zaktualizowaną wersję), ponieważ kod, na który patrzysz, ma 3 lata.
Kerry Jones
13
@ernix - Operator poprosił o JavaScript, odpowiedź, którą udzieliłem, to JavaScript. To jest interpretacja JavaScript funkcji PHP.
Kerry Jones
2
@ernix - działa dokładnie tak, jak oczekiwano na przykładzie podanym przez OP. Położyłem skrzypce, żebyś mógł zobaczyć.
Kerry Jones
4
@ernix - OK, ale chodzi o to, że robi dokładnie to , o co poprosił PO. Pochodzi z innej strony (nie utrzymywanej przeze mnie i już to stwierdziłem), a podając odpowiednie zmienne, działa dokładnie tak, jak podano. Jeśli uważasz, że to błąd, skontaktuj się z phpjs.org lub sprawdź, czy mają zaktualizowaną wersję.
Kerry Jones
75

Jest to odmiana odpowiedzi @ mikez302, ale zmodyfikowana w celu obsługi liczb dziesiętnych (według opinii @ neu-rah, że liczbaWithCommas (12345.6789) -> „12 345,6,789” zamiast „12 345 6789”

function numberWithCommas(n) {
    var parts=n.toString().split(".");
    return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
}
użytkownik1437663
źródło
67
function formatNumber (num) {
    return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
}

print(formatNumber(2665));      // 2,665
print(formatNumber(102665));    // 102,665
print(formatNumber(111102665)); // 111,102,665
Tutenchamona
źródło
Co to robi, że moja odpowiedź nie? Wyrażenie regularne wygląda nieco inaczej, ale wygląda na to, że powinno zrobić to samo.
Elias Zamaria,
8
jest krótszy :)
Tutankhamen
4
To jest eleganckie. Dokładnie tego szukałem.
tradycyjny
4
Z blog.tompawlak.org/number-currency-formatting-javascript ? Znany problem: formatNumber (0.123456) = 0.123,456 Brak lookbehind w JS utrudnia naprawienie go za pomocą eleganckiego wyrażenia regularnego.
Vlad
1
123456789.123456789.toString (). Replace (/ (\ d) (? = (\ D {3}) + \.) / G, '1 $,') => 123
456
53

Używanie wyrażenia regularnego

function toCommas(value) {
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
console.log(toCommas(123456789)); // 123,456,789

console.log(toCommas(1234567890)); // 1,234,567,890
console.log(toCommas(1234)); // 1,234

Korzystanie z toLocaleString ()

var number = 123456.789;

// request a currency format
console.log(number.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' }));
// → 123.456,79 €

// the Japanese yen doesn't use a minor unit
console.log(number.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }))
// → ¥123,457

// limit to three significant digits
console.log(number.toLocaleString('en-IN', { maximumSignificantDigits: 3 }));
// → 1,23,000

ref MDN: Number.prototype.toLocaleString ()

Korzystanie z Intl.NumberFormat ()

var number = 123456.789;

console.log(new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(number));
// expected output: "123.456,79 €"

// the Japanese yen doesn't use a minor unit
console.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number));
// expected output: "¥123,457"

// limit to three significant digits
console.log(new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(number));

// expected output: "1,23,000"

ref Intl.NumberFormat

DEMO W TUTAJ

<script type="text/javascript">
  // Using Regular expression
  function toCommas(value) {
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  }

  function commas() {
    var num1 = document.myform.number1.value;

    // Using Regular expression
    document.getElementById('result1').value = toCommas(parseInt(num1));
    // Using toLocaleString()

    document.getElementById('result2').value = parseInt(num1).toLocaleString('ja-JP', {
      style: 'currency',
      currency: 'JPY'
    });

    // Using Intl.NumberFormat()
    document.getElementById('result3').value = new Intl.NumberFormat('ja-JP', {
      style: 'currency',
      currency: 'JPY'
    }).format(num1);
  }
</script>
<FORM NAME="myform">
  <INPUT TYPE="text" NAME="number1" VALUE="123456789">
  <br>
  <INPUT TYPE="button" NAME="button" Value="=>" onClick="commas()">
  <br>Using Regular expression
  <br>
  <INPUT TYPE="text" ID="result1" NAME="result1" VALUE="">
  <br>Using toLocaleString()
  <br>
  <INPUT TYPE="text" ID="result2" NAME="result2" VALUE="">
  <br>Using Intl.NumberFormat()
  <br>
  <INPUT TYPE="text" ID="result3" NAME="result3" VALUE="">

</FORM>

Wydajność

Wydajność http://jsben.ch/sifRd

Tính Ngô Quang
źródło
To nie działa, jeśli piszesz dynamicznie. Jeśli tylko nadasz mu wartość, to zadziała, ale jeśli ciągle podajesz wartość dynamicznie, przecinki są dodawane w niewłaściwym miejscu.
Edgar Quintero
Zaktualizowałem demo poniżej mojej odpowiedzi. Podczas wprowadzania wartości dynamicznej w polu tekstowym. testujesz spróbuj @EdgarQuintero
Tính Ngô Quang
39

Intl.NumberFormat

Natywna funkcja JS. Obsługiwane przez IE11, Edge, najnowsze Safari, Chrome, Firefox, Opera, Safari na iOS i Chrome na Androida.

var number = 3500;

console.log(new Intl.NumberFormat().format(number));
// → '3,500' if in US English locale
Dustin Sun
źródło
Moja odpowiedź została zaktualizowana w odpowiedzi na twoje komentarze. Dzięki!
Dustin Sun
35

Dziękujemy wszystkim za odpowiedzi. Zbudowałem niektóre z odpowiedzi, aby stworzyć bardziej „uniwersalne” rozwiązanie.

Pierwszy fragment dodaje funkcję, która naśladuje PHP „S number_format()do prototypu Number. Jeśli formatuję liczbę, zwykle chcę miejsc dziesiętnych, więc funkcja przyjmuje liczbę miejsc dziesiętnych do wyświetlenia. Niektóre kraje używają przecinków jako dziesiętnych i dziesiętnych jako separatora tysięcy, więc funkcja umożliwia ustawienie tych separatorów.

Number.prototype.numberFormat = function(decimals, dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.toFixed(decimals).split('.');
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousands_sep);

    return parts.join(dec_point);
}

Użyłbyś tego w następujący sposób:

var foo = 5000;
console.log(foo.numberFormat(2)); // us format: 5,000.00
console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00

Odkryłem, że często potrzebowałem odzyskać liczbę dla operacji matematycznych, ale parseFloat konwertuje 5000 na 5, po prostu biorąc pierwszą sekwencję wartości całkowitych. Stworzyłem więc własną funkcję konwersji float i dodałem ją do prototypu String.

String.prototype.getFloat = function(dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.split(dec_point);
    var re = new RegExp("[" + thousands_sep + "]");
    parts[0] = parts[0].replace(re, '');

    return parseFloat(parts.join(dec_point));
}

Teraz możesz korzystać z obu funkcji w następujący sposób:

var foo = 5000;
var fooString = foo.numberFormat(2); // The string 5,000.00
var fooFloat = fooString.getFloat(); // The number 5000;

console.log((fooString.getFloat() + 1).numberFormat(2)); // The string 5,001.00
Żaden
źródło
2
Bardzo fajnie, pożyczyłem pierwszą metodę;) Ale nie daje to poprawnego wyniku, jeśli chcesz użyć formatu europejskiego, a liczba jest ułamkowa. Wiersz 5 powinien brzmieć:var parts = this.toFixed(decimals).toString().split('.');
vbwx
Masz rację! toFixed () zmienia przecinek na kropkę, a zatem „.” należy użyć zamiast var dec_point. Dzięki za zwrócenie na to uwagi.
Brak
czy możesz zrobić do tego moduł npm?
chovy
3
@ J.Money .toString nie jest konieczne, toFixed już zwraca łańcuch.
Ariel
Nie wiem, dlaczego w ogóle wspomniałeś tutaj o PHP, ani nie
nadałeś
27

Jestem pod wrażeniem liczby odpowiedzi, jakie otrzymałem na to pytanie. Podoba mi się odpowiedź uKolka :

n.toLocaleString()

Niestety, w niektórych lokalizacjach, takich jak hiszpański, nie działa (IMHO) zgodnie z oczekiwaniami dla liczb poniżej 10 000:

Number(1000).toLocaleString('ES-es')

Daje 1000i nie 1.000.

Zobacz , dlaczego toLocaleString nie działa na liczbach mniejszych niż 10000 we wszystkich przeglądarkach, aby wiedzieć, dlaczego.

Musiałem więc użyć odpowiedzi Eliasa Zamarii, wybierając odpowiedni znak separatora tysięcy:

n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, Number(10000).toLocaleString().substring(2, 3))

Ten działa dobrze jako jednolinijka dla obu lokalizacji, które używają ,lub .jako separatora tysięcy, i zaczyna działać od 1000 we wszystkich przypadkach.

Number(1000).toString().replace(/\B(?=(\d{3})+(?!\d))/g, Number(10000).toLocaleString().substring(2, 3))

Daje 1.000w kontekście hiszpańskich ustawień regionalnych.

Jeśli chcesz mieć absolutną kontrolę nad sposobem formatowania liczby, możesz również spróbować:

let number   = 1234.567
let decimals = 2
let decpoint = '.' // Or Number(0.1).toLocaleString().substring(1, 2)
let thousand = ',' // Or Number(10000).toLocaleString().substring(2, 3)

let n = Math.abs(number).toFixed(decimals).split('.')
n[0] = n[0].split('').reverse().map((c, i, a) =>
  i > 0 && i < a.length && i % 3 == 0 ? c + thousand : c
).reverse().join('')
let final = (Math.sign(number) < 0 ? '-' : '') + n.join(decpoint)

console.log(final)

Daje 1,234.57.

Ten nie wymaga wyrażenia regularnego. Działa poprzez dostosowanie liczby do pożądanej liczby miejsc po przecinku za pomocą toFixednajpierw, a następnie podzielenie jej wokół punktu dziesiętnego, .jeśli taki istnieje. Lewa strona jest następnie przekształcana w tablicę cyfr, która jest odwrócona. Następnie separator tysięcy jest dodawany co trzy cyfry od początku, a wynik ponownie odwracany. Ostatecznym rezultatem jest połączenie dwóch części. Znak numeru wejściowego jest Math.absnajpierw usuwany, a następnie w razie potrzeby odkładany.

Nie jest to jedna linijka, ale niewiele dłużej i łatwo można ją przekształcić w funkcję. Zmienne zostały dodane dla jasności, ale można je zastąpić ich pożądanymi wartościami, jeśli są znane z góry. Możesz użyć wyrażeń, które wykorzystają toLocaleStringjako sposób na znalezienie odpowiednich znaków po przecinku i separatora tysięcy dla bieżących ustawień narodowych (pamiętaj, że wymagają one bardziej nowoczesnego Javascript).

Javier Elices
źródło
23

Myślę, że to najkrótsze wyrażenie regularne, które to robi:

/\B(?=(\d{3})+\b)/g

"123456".replace(/\B(?=(\d{3})+\b)/g, ",")

Sprawdziłem to na kilku numerach i zadziałało.

użytkownik3664916
źródło
działa dobrze tylko wtedy, gdy nie ma liczb zmiennoprzecinkowych z więcej niż 3 liczbami po separatorze, w tym przypadku kropka. W przeciwnym razie dodaje także przecinek. „1234567890.1234567890” .replace (/ \ B (? = (\ D {3}) + \ b) / g, ",") To nie działałoby na przykład. Zwraca „1 234 567 890,1 224 576 890”
Marcio,
1
Działa dobrze dla waluty! Po prostu zaokrąglij cyfry przed dodaniem przecinków.
Kyle Chadha,
1
Po kropce dziesiętnej dodaje: 12.3456 ".replace (/ \ B (? = (\ D {3}) + \ b) / g,", ") == 123,456
Shree Tiwari
21

Number.prototype.toLocaleString()byłby niesamowity, gdyby był dostarczany natywnie przez wszystkie przeglądarki (Safari) .

Sprawdziłem wszystkie inne odpowiedzi, ale chyba nikt ich nie wypełnił. Oto pocenie w tym kierunku, które jest właściwie kombinacją dwóch pierwszych odpowiedzi; jeśli toLocaleStringdziała, używa go, jeśli nie, używa niestandardowej funkcji.

var putThousandsSeparators;

putThousandsSeparators = function(value, sep) {
  if (sep == null) {
    sep = ',';
  }
  // check if it needs formatting
  if (value.toString() === value.toLocaleString()) {
    // split decimals
    var parts = value.toString().split('.')
    // format whole numbers
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);
    // put them back together
    value = parts[1] ? parts.join('.') : parts[0];
  } else {
    value = value.toLocaleString();
  }
  return value;
};

alert(putThousandsSeparators(1234567.890));

Sinan
źródło
1
Pamiętaj, że wypełniacz działa tylko z liczbami, które mają najwyżej 3 miejsca po przecinku. Na przykład: 0.12345wyświetli 0.12,345. Dobrą implementację do tego można znaleźć w Underscore.string
Andy
masz rację, value > 1000ustawienie warunku if naprawia ten przypadek, ale był to poc i oczywiście lepiej przetestowane wersje można znaleźć gdzie indziej, dzięki za zwrócenie uwagi.
Sinan
1
Nie wystarczy value > 1000podać, ponieważ byłby taki sam dla dowolnej liczby i więcej niż 3 miejsc po przecinku. np . 1000.12345zwraca 1,000.12,345. Twoja odpowiedź jest świetna i na właściwej ścieżce, ale po prostu niepełna. Próbowałem tylko wskazać na inne osoby, które mogą natknąć się na twoją odpowiedź i po prostu skopiować / wkleić ją bez testowania z różnymi danymi wejściowymi.
Andy
1
w porządku, to wymagało kolejnej edycji :) Zgadzam się, ale teraz przynajmniej powinno działać w większości przypadków.
Sinan
18

Separator tysięcy można wstawić w przyjazny dla świata sposób za pomocą Intlobiektu przeglądarki :

Intl.NumberFormat().format(1234);
// returns "1,234" if the user's locale is en_US, for example

Zobacz artykuł MDN na temat NumberFormat, aby dowiedzieć się więcej, możesz określić zachowanie regionalne lub domyślne dla użytkownika. Jest to nieco bardziej niezawodne, ponieważ uwzględnia lokalne różnice; wiele krajów używa kropek do oddzielania cyfr, a przecinek oznacza miejsca po przecinku.

Intl.NumberFormat nie jest jeszcze dostępny we wszystkich przeglądarkach, ale działa w najnowszych przeglądarkach Chrome, Opera i IE. Kolejne wydanie Firefoksa powinno go obsługiwać. Wydaje się, że Webkit nie ma harmonogramu wdrożenia.

phette23
źródło
2
Chociaż byłoby to niesamowite, gdybyśmy mogli użyć prostej wbudowanej funkcji, ma ona straszną implementację przeglądarki. Na przykład IE 8-10 i wszystkie Safari tego nie obsługują
Blaine Kasten
@ BlaineKasten jest dostępny w pełni kompatybilny wypełniacz dla starszych przeglądarek dostępny tutaj: github.com/andyearnshaw/Intl.js jest ogromny, ale działa.
Mahn
1
Dostępne za pośrednictwem CDN z pollyfill (zwraca tylko to, co jest potrzebne w oparciu o useragent): cdn.polyfill.io/v2/polyfill.min.js?features=Intl
Kevin
Miałem problemy z formatowaniem dużych liczb za pomocą toLocaleString, działało to świetnie (z polifillem)
zapytał_io
18

Możesz użyć tej procedury do sformatowania potrzebnej waluty.

var nf = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});
nf.format(123456.789); // ‘$123,456.79’

Aby uzyskać więcej informacji, możesz uzyskać dostęp do tego linku.

https://www.justinmccandless.com/post/formatting-currency-in-javascript/

Dulith De Costa
źródło
To jest poprawna, przenośna, natywna odpowiedź. Chciałbym móc głosować więcej niż raz.
Jared Smith
14

jeśli masz do czynienia z wartościami walutowymi i dużo formatujesz, może warto dodać malutką księgowość.js, która obsługuje wiele przypadków brzegowych i lokalizacji:

// Default usage:
accounting.formatMoney(12345678); // $12,345,678.00

// European formatting (custom symbol and separators), could also use options object as second param:
accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99

// Negative values are formatted nicely, too:
accounting.formatMoney(-500000, "£ ", 0); // £ -500,000

// Simple `format` string allows control of symbol position [%v = value, %s = symbol]:
accounting.formatMoney(5318008, { symbol: "GBP",  format: "%v %s" }); // 5,318,008.00 GBP
Shital Shah
źródło
1
Link już nie działa. Ale wygląda podobnie do tego: openexchangerates.github.io/accounting.js
ush189
13

Poniższy kod wykorzystuje skanowanie znaków, więc nie ma wyrażenia regularnego.

function commafy( num){
  var parts = (''+(num<0?-num:num)).split("."), s=parts[0], L, i=L= s.length, o='';
  while(i--){ o = (i===0?'':((L-i)%3?'':',')) 
                  +s.charAt(i) +o }
  return (num<0?'-':'') + o + (parts[1] ? '.' + parts[1] : ''); 
}

Pokazuje obiecującą wydajność: http://jsperf.com/number-formatting-with-commas/5

2015.4.26: Drobna poprawka rozwiązująca problem, gdy numer <0. Zobacz https://jsfiddle.net/runsun/p5tqqvs3/

uruchamia się
źródło
to nie działa z commafy(-123456)tym daje-,123,456
wrossmck
To jest świetne! Dzięki za złożenie jsperf
fregante
Ten fragment jest absolutnym potworem, który wykonuje wszystko.
NiCk Newman
13

Oto prosta funkcja, która wstawia przecinki dla tysięcy separatorów. Używa funkcji tablicowych zamiast RegEx.

/**
 * Format a number as a string with commas separating the thousands.
 * @param num - The number to be formatted (e.g. 10000)
 * @return A string representing the formatted number (e.g. "10,000")
 */
var formatNumber = function(num) {
    var array = num.toString().split('');
    var index = -3;
    while (array.length + index > 0) {
        array.splice(index, 0, ',');
        // Decrement by 4 since we just added another unit to the array.
        index -= 4;
    }
    return array.join('');
};

Link CodeSandbox z przykładami: https://codesandbox.io/s/p38k63w0vq

Noah Freitas
źródło
1
Cześć .. Ten przykład jest świetny. Ale wstawi przecinki również dla części dziesiętnej. po prostu edycja: funkcja formatNumber (num) {var decimalPart = ''; num = num.toString (); if (num.indexOf ('.')! = -1) {decimalPart = '.' + num.split ('.') [1]; num = parseInt (num.split ('.') [0]); } var array = num.toString (). split (''); indeks var = -3; while (array.length + index> 0) {array.splice (index, 0, ','); // Zmniejszenie o 4, ponieważ właśnie dodaliśmy kolejną jednostkę do tablicy. indeks - = 4; } return array.join ('') + decimalPart; };
Aki143S,
Dziękuję Panu. Właśnie tego potrzebowałem.
Amir Hossein Ahmadi
11

Użyj tego kodu do obsługi formatu waluty dla Indii. Kod kraju można zmienić w celu obsługi innej waluty krajowej.

let amount =350256.95
var formatter = new Intl.NumberFormat('en-IN', {
  minimumFractionDigits: 2,
});

// Use it.

formatter.format(amount);

wynik:

3,50,256.95
Bathri Nathan
źródło
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi. Przeczytaj to .
Shanteshwar Inde,
@ShanteshwarInde dodam dodatkowy kontekst, aby poprawić odpowiedź na pewno
Bathri Nathan
11

Możesz także użyć konstruktora Intl.NumberFormat . Oto jak możesz to zrobić.

 resultNumber = new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(yourNumber); 
Oliver
źródło
ten nie działa węzeł js. Nie
udziela
7

Napisałem to przed natknięciem się na ten post. Bez wyrażeń regularnych i możesz naprawdę zrozumieć kod.

$(function(){
  
  function insertCommas(s) {

    // get stuff before the dot
    var d = s.indexOf('.');
    var s2 = d === -1 ? s : s.slice(0, d);

    // insert commas every 3 digits from the right
    for (var i = s2.length - 3; i > 0; i -= 3)
      s2 = s2.slice(0, i) + ',' + s2.slice(i);

    // append fractional part
    if (d !== -1)
      s2 += s.slice(d);

    return s2;

  }
  
  
  $('#theDudeAbides').text( insertCommas('1234567.89012' ) );
  
  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="theDudeAbides"></div>

Ronnie Overby
źródło
1
Dodałem s.toString () na początku funkcji, aby mógł akceptować również liczby, a nie tylko łańcuchy. To jest moja preferowana odpowiedź, ponieważ jest czytelna, zwięzła i nie zawiera błędów, które wydają się zawierać odpowiedzi regularne.
FeFiFoFu
7
var formatNumber = function (number) {
  var splitNum;
  number = Math.abs(number);
  number = number.toFixed(2);
  splitNum = number.split('.');
  splitNum[0] = splitNum[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  return splitNum.join(".");
}

EDYCJA: Funkcja działa tylko z liczbą dodatnią. na przykład:

var number = -123123231232;
formatNumber(number)

Wyjście: „123 123 123 232 232”

Ale odpowiedź na powyższe pytanie toLocaleString()rozwiązuje problem.

var number = 123123231232;
    number.toLocaleString()

Wyjście: „123 123 123 232 232”

Dopingować!

Kiry Meas
źródło
1
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Kaczor Donald
1
Fajny skrypt, ale nie działa z liczbami ujemnymi.
Ralph David Abernathy
7

Moja odpowiedź jest jedyną odpowiedzią, która całkowicie zastępuje jQuery bardziej sensowną alternatywą:

function $(dollarAmount)
{
    const locale = 'en-US';
    const options = { style: 'currency', currency: 'USD' };
    return Intl.NumberFormat(locale, options).format(dollarAmount);
}

To rozwiązanie nie tylko dodaje przecinki, ale także zaokrągla do najbliższego grosza, jeśli wpiszesz kwotę, np. $(1000.9999)Dostaniesz 1 001 USD. Dodatkowo wprowadzana wartość może być bezpiecznie liczbą lub łańcuchem; to nie ma znaczenia.

Jeśli masz do czynienia z pieniędzmi, ale nie chcesz, aby na kwoty pokazywał się wiodący znak dolara, możesz również dodać tę funkcję, która korzysta z poprzedniej funkcji, ale usuwa $:

function no$(dollarAmount)
{
    return $(dollarAmount).replace('$','');
}

Jeśli nie do czynienia z pieniędzmi, i mają różne wymagania formatowanie dziesiętne, tutaj jest bardziej wszechstronny funkcji:

function addCommas(number, minDecimalPlaces = 0, maxDecimalPlaces = Math.max(3,minDecimalPlaces))
{
    const options = {};
    options.maximumFractionDigits = maxDecimalPlaces;
    options.minimumFractionDigits = minDecimalPlaces;
    return Intl.NumberFormat('en-US',options).format(number);
}

A tak przy okazji, fakt, że ten kod nie działa w niektórych starych wersjach Internet Explorera, jest całkowicie zamierzony. Staram się przełamać IE za każdym razem, kiedy mogę go złapać, nie wspierając nowoczesnych standardów.

Pamiętaj, że nadmierne pochwały w komentarzach są uważane za nie na temat. Zamiast tego, po prostu obsyp mnie mnie głosami większymi.

Lonnie Best
źródło
1
Number (n) .toLocaleString () wydaje się najlepszą odpowiedzią, ale prawdopodobnie będziesz chciał użyć czegoś takiego jak nowy Intl.NumberFormat ('en-US'). Format (n) zamiast usuwania znaków dolara i dziesiętnych, jeśli wszystkie użytkownik chce przecinków w ich liczbie.
bmacnaughton,
@bmacnaughton: To dobry moment, gdy nie masz do czynienia z pieniędzmi. Jeśli jednak masz do czynienia z pieniędzmi i po prostu „nie chcesz wiodącego znaku dolara”, liczba (1000,50) .toLocaleString () generuje „1000,5”, co usuwa nieznaczne zero, które zwykle zachowuje się podczas wyświetlania wartości pieniędzy. Dobry komentarz: wszyscy powinni wiedzieć, co powiedziałeś.
Lonnie Best,
6

Dla mnie najlepszą odpowiedzią jest użycie metody toLocaleString, jak powiedzieli niektórzy członkowie. Jeśli chcesz dołączyć symbol „$”, po prostu dodaj languaje i wpisz opcje. Oto i przykład sformatowania liczby w peso meksykańskie

var n = 1234567.22
alert(n.toLocaleString("es-MX",{style:"currency", currency:"MXN"}))

skrót

1234567.22.toLocaleString("es-MX",{style:"currency", currency:"MXN"})
Carlos A. Ortiz
źródło
5

Pozwól mi spróbować poprawić uKolka „s odpowiedź i może pomóc innym zaoszczędzić trochę czasu.

Użyj Numeral.js .

document.body.textContent = numeral(1234567).format('0,0');
<script src="//cdnjs.cloudflare.com/ajax/libs/numeral.js/1.4.5/numeral.min.js"></script>

Powinieneś korzystać z Number.prototype.toLocaleString () tylko wtedy, gdy kompatybilność przeglądarki nie stanowi problemu.

Beder Acosta Borges
źródło
zainspirowało mnie to do zainstalowania npm numeral
steampowered
5

Alternatywny sposób, obsługujący miejsca po przecinku, różne separatory i negatywy.

var number_format = function(number, decimal_pos, decimal_sep, thousand_sep) {
    var ts      = ( thousand_sep == null ? ',' : thousand_sep )
        , ds    = ( decimal_sep  == null ? '.' : decimal_sep )
        , dp    = ( decimal_pos  == null ? 2   : decimal_pos )

        , n     = Math.floor(Math.abs(number)).toString()

        , i     = n.length % 3 
        , f     = ((number < 0) ? '-' : '') + n.substr(0, i)
    ;

    for(;i<n.length;i+=3) {
        if(i!=0) f+=ts;
        f+=n.substr(i,3);
    }

    if(dp > 0) 
        f += ds + parseFloat(number).toFixed(dp).split('.')[1]

    return f;
}

Kilka poprawek @Jignesh Sanghani, nie zapomnij pochwalić jego komentarza.

Felipe Buccioni
źródło
Idealne dla mnie, właśnie dodałem nową linię, aby usunąć formatowanie przed przetwarzaniem.
Dennis Heiden,
2
fn.substr(0, i)zamień na, n.substr(0, i)a także number.toFixed(dp).split('.')[1]zamień na parseFloat(number).toFixed(dp).split('.')[1]. ponieważ kiedy używam bezpośrednio, daje mi to błąd. zaktualizuj swój kod
Jignesh Sanghani,
wadliwy. liczba rośnie. połączenie z exampelem byłoby świetne!
mmm,
zmiana sufitu na podłogę naprawiła to, ale nie jest pewna, jakie będą inne problemy.
mmm,
1
Spróbuj Math.floor (-75,1);)
mmm
4

Myślę, że ta funkcja zajmie się wszystkimi problemami związanymi z tym problemem.

function commaFormat(inputString) {
    inputString = inputString.toString();
    var decimalPart = "";
    if (inputString.indexOf('.') != -1) {
        //alert("decimal number");
        inputString = inputString.split(".");
        decimalPart = "." + inputString[1];
        inputString = inputString[0];
        //alert(inputString);
        //alert(decimalPart);

    }
    var outputString = "";
    var count = 0;
    for (var i = inputString.length - 1; i >= 0 && inputString.charAt(i) != '-'; i--) {
        //alert("inside for" + inputString.charAt(i) + "and count=" + count + " and outputString=" + outputString);
        if (count == 3) {
            outputString += ",";
            count = 0;
        }
        outputString += inputString.charAt(i);
        count++;
    }
    if (inputString.charAt(0) == '-') {
        outputString += "-";
    }
    //alert(outputString);
    //alert(outputString.split("").reverse().join(""));
    return outputString.split("").reverse().join("") + decimalPart;
}
AbhinavRanjan
źródło
4

Tylko dla przyszłych Googlersów (lub niekoniecznie „Googlersów”):

Wszystkie powyższe rozwiązania są wspaniałe, jednak RegExp może być okropnie złą rzeczą w takiej sytuacji.

Tak, możesz użyć niektórych z proponowanych opcji lub nawet napisać coś prymitywnego, ale przydatnego, takiego jak:

const strToNum = str => {

   //Find 1-3 digits followed by exactly 3 digits & a comma or end of string
   let regx = /(\d{1,3})(\d{3}(?:,|$))/;
   let currStr;

   do {
       currStr = (currStr || str.split(`.`)[0])
           .replace( regx, `$1,$2`)
   } while (currStr.match(regx)) //Stop when there's no match & null's returned

   return ( str.split(`.`)[1] ) ?
           currStr.concat(`.`, str.split(`.`)[1]) :
           currStr;

};

strToNum(`123`) // => 123
strToNum(`123456`) // => 123,456
strToNum(`-1234567.0987`) // => -1,234,567.0987

Wyrażenie regularne, które tu zastosowano, jest dość proste, a pętla przejdzie dokładnie tyle razy, ile potrzeba, aby wykonać zadanie.

Możesz go zoptymalizować znacznie lepiej, kodować „DRYify” i tak dalej.

Jeszcze,

(-1234567.0987).toLocaleString();

(w większości sytuacji) byłby zdecydowanie lepszym wyborem.

Nie chodzi o szybkość wykonywania ani kompatybilność z różnymi przeglądarkami.

W sytuacjach, gdy chcesz pokazać wynikowy numer użytkownikowi, metoda .toLocaleString () daje ci superumiejętność mówienia tym samym językiem z użytkownikiem witryny lub aplikacji (niezależnie od tego, jaki jest jego język).

Ta metoda zgodnie z dokumentacją ECMAScript została wprowadzona w 1999 r. I uważam, że powodem tego była nadzieja, że ​​Internet w pewnym momencie połączy ludzi na całym świecie, dlatego potrzebne były pewne narzędzia „internalizacji”.

Dzisiaj Internet łączy nas wszystkich, dlatego ważne jest, aby pamiętać, że świat jest znacznie bardziej złożony, niż moglibyśmy to sobie wyobrazić, i że (/ prawie) wszyscy jesteśmy tutaj , w Internecie.

Oczywiście, biorąc pod uwagę różnorodność ludzi, nie jest możliwe zagwarantowanie każdemu idealnego UX, ponieważ mówimy różnymi językami, cenimy różne rzeczy itp. I właśnie z tego powodu jeszcze ważniejsze jest, aby spróbować zlokalizować rzeczy tak bardzo, jak to możliwe .

Biorąc pod uwagę, że istnieją pewne szczególne standardy reprezentacji daty, godziny, liczb itp. I że mamy narzędzie do wyświetlania tych rzeczy w formacie preferowanym przez użytkownika końcowego, nie jest to rzadkie i prawie nieodpowiedzialne, aby nie skorzystać z tego narzędzia (szczególnie w sytuacjach, gdy chcemy wyświetlić te dane użytkownikowi)?

Dla mnie używanie RegExp zamiast .toLocaleString () w takiej sytuacji brzmi trochę jak tworzenie aplikacji zegara z JavaScript i kodowanie go w taki sposób, aby wyświetlał tylko czas w Pradze (co byłoby całkiem bezużyteczne dla ludzie, którzy nie mieszkają w Pradze), mimo że zachowanie domyślne

new Date();

jest zwracanie danych zgodnie z zegarem użytkownika końcowego.

Igor Bykow
źródło
dlaczego napisałeś funkcję z const i =>?
OG Sean
@OGSean Zawsze to robię, ponieważ jest to najwygodniejszy sposób deklarowania zmiennych i funkcji. Myślę też, że pomaga to w utrzymaniu czystszego i krótszego kodu.
Igor Bykov,
4

Moje prawdziwe rozwiązanie tylko dla wyrażeń regularnych dla tych, którzy kochają jedno-linijki

Widzisz tych entuzjastycznych graczy powyżej? Może możesz z tego grać w golfa. Oto mój ruch.

n => `${n}`.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " ").replace(/(?<=\.(\d{3})+)\B/g, " ")

Używa CIENKIEJ PRZESTRZENI (U + 2009) dla separatora tysięcy, jak to powiedział Międzynarodowy System Jednostek w ósmym wydaniu (2006) ich publikacji „ SI Broszura: Międzynarodowy System Jednostek (SI) (patrz § 5.3 .4.). Dziewiąte wydanie (2019) sugeruje, aby wykorzystać na to miejsce (patrz §5.4.4.). Możesz użyć, co chcesz, w tym przecinek.


Widzieć.

const integer_part_only = n => `${n}`.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ");
const fractional_part_only = n => `${n}`.replace(/(?<=\.(\d{3})+)\B/g, " F ");
const both = n => fractional_part_only(integer_part_only(n));

function demo(number) { // I’m using Chrome 74.
	console.log(`${number}
		 "${integer_part_only(number)}" (integer part only)
		 "${fractional_part_only(number)}" (fractional part only)
		 "${both(number)}" (both)
	`);
}
demo(Math.random() * 10e5);
demo(123456789.01234567);
demo(123456789);
demo(0.0123456789);


Jak to działa?

Dla części całkowitej

.replace(/(?<!\.\d+)\B(?=(\d{3})+\b)/g, " I ")
  • .replace(……, " I ") Wpisz „ja”
    • /……/g na każdym z
      • \B pomiędzy dwiema sąsiednimi cyframi
        • (?=……)POZYTYWNA LOOKAHEAD, której prawą częścią jest
          • (\d{3})+ jeden lub więcej trzycyfrowych fragmentów
          • \b po którym następuje cyfra, taka jak kropka, zakończenie łańcucha itp.
        • (?<!……)NEGATYWNE SPOJRZENIE, wyłączając te, których lewa część
          • \.\d+ to kropka, po której następują cyfry („ma separator dziesiętny”).

Za część dziesiętną

.replace(/(?<=\.(\d{3})+)\B/g, " F ")
  • .replace(……, " F ") Wpisz „F”
    • /……/g na każdym z
      • \B pomiędzy dwiema sąsiednimi cyframi
        • (?<=……)POZYTYWNE SPOJRZENIE, którego lewą częścią jest
          • \. separator dziesiętny
          • (\d{3})+ a następnie jeden lub więcej trzycyfrowych fragmentów.

Klasy postaci i granice

\d

Pasuje do dowolnej cyfry (cyfra arabska). Odpowiednik [0-9].

Na przykład,

  • /\d/lub /[0-9]/mecze 2w B2 is the suite number.

\b

Dopasowuje granicę słowa . Jest to miejsce, w którym znak słowny nie jest poprzedzony lub poprzedzony innym znakiem słownym, na przykład między literą a spacją. Pamiętaj, że dopasowana granica słów nie jest uwzględniana w dopasowaniu. Innymi słowy, długość dopasowanej granicy słów wynosi zero.

Przykłady:

  • /\bm/dopasowuje msię moon;
  • /oo\b/nie pasuje do ooin moon, ponieważ oonastępuje nktóry jest postacią słowo;
  • /oon\b/dopasowuje oonin moon, ponieważ oonjest końcem ciągu, a zatem nie następuje po nim znak słowny;
  • /\w\b\w/ nigdy nie będzie pasować do niczego, ponieważ po słowie nigdy nie może występować zarówno znak niebędący słowem, jak i znak słowny.

\B

Dopasowuje granicę inną niż słowo . Jest to pozycja, w której poprzedni i następny znak są tego samego typu: oba muszą być słowami, lub oba muszą być nie słowami. Na przykład między dwiema literami lub między dwiema spacjami. Początek i koniec łańcucha są traktowane jako słowa bez słów. Podobnie jak dopasowana granica słowa, dopasowana granica słowa nie jest również uwzględniana w dopasowaniu.

Na przykład,

  • /\Bon/mecze onw at noon;
  • /ye\B/mecze yew possibly yesterday.

Kompatybilność z przeglądarkami

Константин Ван
źródło
3

Dodałem tofixed do rozwiązania Aki143S . To rozwiązanie wykorzystuje kropki dla tysięcy separatorów i przecinek dla precyzji.

function formatNumber( num, fixed ) { 
    var decimalPart;

    var array = Math.floor(num).toString().split('');
    var index = -3; 
    while ( array.length + index > 0 ) { 
        array.splice( index, 0, '.' );              
        index -= 4;
    }

    if(fixed > 0){
        decimalPart = num.toFixed(fixed).split(".")[1];
        return array.join('') + "," + decimalPart; 
    }
    return array.join(''); 
};

Przykłady;

formatNumber(17347, 0)  = 17.347
formatNumber(17347, 3)  = 17.347,000
formatNumber(1234563.4545, 3)  = 1.234.563,454
Bartburkhardt
źródło
3

Wiele dobrych odpowiedzi już. Oto kolejna, dla zabawy:

function format(num, fix) {
    var p = num.toFixed(fix).split(".");
    return p[0].split("").reduceRight(function(acc, num, i, orig) {
        if ("-" === num && 0 === i) {
            return num + acc;
        }
        var pos = orig.length - i - 1
        return  num + (pos && !(pos % 3) ? "," : "") + acc;
    }, "") + (p[1] ? "." + p[1] : "");
}

Kilka przykładów:

format(77.03453, 2); // "77.03"
format(78436589374); // "78,436,589,374"
format(784, 4);      // "784.0000"
format(-123456);     // "-123,456"
Wayne
źródło
to nie działa z format(-123456)tym daje-,123,456
wrossmck
1
Naprawiono (chociaż prawdopodobnie jest to bardziej elegancki sposób, aby za każdym razem nie sprawdzać znaku). W każdym razie aktualizacja sprawia, że ​​działa to z liczbami ujemnymi.
Wayne