Snažím se vytisknout celé číslo v JavaScriptu s čárkami jako oddělovači tisíců. Například chci zobrazit číslo 1234567 jako „1 234 567“. Jak bych to udělal?
Zde je návod, jak to dělám:
function numberWithCommas(x) { x = x.toString(); var pattern = /(-?d+)(d{3})/; while (pattern.test(x)) x = x.replace(pattern, "$1,$2"); return x; }
Existuje jednodušší nebo elegantnější způsob, jak to udělat? Bylo by hezké, kdyby to fungovalo i s plováky, ale to není nutné. K rozhodování mezi tečkami a čárkami nemusí být specifické pro národní prostředí.
Odpověď
Použil jsem nápad z Kerryho odpovědi, ale zjednodušil jsem to, protože jsem jen hledal něco jednoduchého pro svůj konkrétní účel. Zde je to, co jsem udělal:
function numberWithCommas(x) { return x.toString().replace(/B(?=(d{3})+(?!d))/g, ","); }
function numberWithCommas(x) { return x.toString().replace(/B(?<!.d*)(?=(d{3})+(?!d))/g, ","); } function test(x, expect) { const result = numberWithCommas(x); const pass = result === expect; console.log(`${pass ? "✓" : "ERROR ====>"} ${x} => ${result}`); return pass; } let failures = 0; failures += !test(0, "0"); failures += !test(100, "100"); failures += !test(1000, "1,000"); failures += !test(10000, "10,000"); failures += !test(100000, "100,000"); failures += !test(1000000, "1,000,000"); failures += !test(10000000, "10,000,000"); if (failures) { console.log(`${failures} test(s) failed`); } else { console.log("All tests passed"); }
.as-console-wrapper { max-height: 100% !important; }
Regulární výraz používá 2 předběžná tvrzení:
- kladné k vyhledání libovolného bodu v řetězci, který má za sebou násobek 3 číslic v řadě,
- záporné tvrzení, aby se zajistilo, že bod má pouze přesně násobek 3 číslic. Náhradní výraz tam vloží čárku.
Pokud jej například předáte 123456789.01
, kladné tvrzení bude odpovídat každému místu nalevo od 7 (od 789
je násobek 3 číslic, 678
je násobek 3 číslic, 567
, atd.). Záporné tvrzení kontroluje, že násobek 3 číslic nemá za sebou žádné číslice. 789
má za sebou tečku, takže je to přesně násobek 3 číslic, takže tam jde čárka. 678
je násobkem 3 číslic, ale má 9
za ním, takže ty 3 číslice jsou součástí skupiny 4 a čárka tam nejde. Podobně pro 567
. 456789
je 6 číslic, což je násobek 3, takže před ním je čárka. 345678
je násobkem 3, ale má 9
za ním, takže tam žádná čárka nejde. A tak dále. B
zabrání regulárnímu výrazu vložit čárku na začátek řetězce.
@neu-rah zmínil, že tato funkce přidává čárky na nežádoucí místa, pokud jsou za desetinnou čárkou více než 3 číslice. Pokud se jedná o problém, můžete použít tuto funkci:
function numberWithCommas(x) { var parts = x.toString().split("."); parts[0] = parts[0].replace(/B(?=(d{3})+(?!d))/g, ","); return parts.join("."); }
function numberWithCommas(x) { var parts = x.toString().split("."); parts[0] = parts[0].replace(/B(?=(d{3})+(?!d))/g, ","); return parts.join("."); } function test(x, expect) { const result = numberWithCommas(x); const pass = result === expect; console.log(`${pass ? "✓" : "ERROR ====>"} ${x} => ${result}`); return pass; } let failures = 0; failures += !test(0 , "0"); failures += !test(0.123456 , "0.123456"); failures += !test(100 , "100"); failures += !test(100.123456 , "100.123456"); failures += !test(1000 , "1,000"); failures += !test(1000.123456 , "1,000.123456"); failures += !test(10000 , "10,000"); failures += !test(10000.123456 , "10,000.123456"); failures += !test(100000 , "100,000"); failures += !test(100000.123456 , "100,000.123456"); failures += !test(1000000 , "1,000,000"); failures += !test(1000000.123456 , "1,000,000.123456"); failures += !test(10000000 , "10,000,000"); failures += !test(10000000.123456, "10,000,000.123456"); if (failures) { console.log(`${failures} test(s) failed`); } else { console.log("All tests passed"); }
.as-console-wrapper { max-height: 100% !important; }
@t.j.crowder poukázal na to, že nyní, když má JavaScript lookbehind (informace o podpoře), lze to vyřešit v samotném regulárním výrazu:
function numberWithCommas(x) { return x.toString().replace(/B(?<!.d*)(?=(d{3})+(?!d))/g, ","); }
function numberWithCommas(x) { return x.toString().replace(/B(?<!.d*)(?=(d{3})+(?!d))/g, ","); } function test(x, expect) { const result = numberWithCommas(x); const pass = result === expect; console.log(`${pass ? "✓" : "ERROR ====>"} ${x} => ${result}`); return pass; } let failures = 0; failures += !test(0, "0"); failures += !test(0.123456, "0.123456"); failures += !test(100, "100"); failures += !test(100.123456, "100.123456"); failures += !test(1000, "1,000"); failures += !test(1000.123456, "1,000.123456"); failures += !test(10000, "10,000"); failures += !test(10000.123456, "10,000.123456"); failures += !test(100000, "100,000"); failures += !test(100000.123456, "100,000.123456"); failures += !test(1000000, "1,000,000"); failures += !test(1000000.123456, "1,000,000.123456"); failures += !test(10000000, "10,000,000"); failures += !test(10000000.123456, "10,000,000.123456"); if (failures) { console.log(`${failures} test(s) failed`); } else { console.log("All tests passed"); }
.as-console-wrapper { max-height: 100% !important; }
(?<!.d*)
je negativní lookbehind, který říká, že shodě nemůže předcházet .
následuje nula nebo více číslic. Negativní lookbehind je rychlejší než split
a join
řešení (srovnání), alespoň ve V8.