javascript - 使用 NumeralJS,我如何根据一个数字是千位还是百万来确定格式
我的标题基本上已经说明了一切,在我的应用程序中,我只在数值大于6位时才进行格式化。当数值是千位数时,例如 210,500,我希望显示为 210.5k;如果数值是百万位,例如 2,120,000,我希望显示为 2.12m。目前格式字符串('0,0.[00]a')会对这两个数都显示相同的小数位,但我希望根据数值是千位还是百万来决定小数位数。
解决这个问题的最好方法是循环遍历这个值直到遇到小数,然后根据这个数字确定格式吗?我尝试过使用自定义格式对象,但很难理解其背后的原理。
此数值显示在卡片上,当数字有6位或更多位时,需要进行格式化。对于千位数的值,应显示1位小数;对于百万位(或更大)的值,应显示2位小数。
期望的输入和输出:
210500 --> 210.5k
2120000 --> 2.12m
67500.89 --> 6.7k
6750000 --> 6.75m
16.75 --> 16.75
67530.85 --> 67.5k
675 --> 675
6700.05 --> 6700
2522.25 --> 2522
function formatValue(value: string | number, shorthandFormat: boolean = true, shorthandLength: number = 6) {
if (value === undefined || value === null) return '?';
let valueString = value.toString();
if (valueString.trim() === '') return '';
if (shorthandFormat) {
if (!shorthandLength || shorthandLength < 0) {
shorthandLength = 6;
}
if (valueString.length <= shorthandLength) {
shorthandFormat = false;
}
}
let numeralValue = numeral(value)
let formatter = shorthandFormat ? '0,0.[0]a' : '0,0.[00]';
let formattedValue = numeralValue.format(formatter);
return formattedValue;
}
可运行的代码片段:
function formatValue(value, shorthandFormat = true, shorthandLength = 6) {
if (value === undefined || value === null) return '?';
let valueString = value.toString();
if (valueString.trim() === '') return '';
if (shorthandFormat) {
if (!shorthandLength || shorthandLength < 0) {
shorthandLength = 6;
}
if (valueString.length <= shorthandLength) {
shorthandFormat = false;
}
}
let numeralValue = numeral(value)
let formatter = shorthandFormat ? '0,0.[0]a' : '0,0.[00]';
let formattedValue = numeralValue.format(formatter);
return formattedValue;
}
// 210,500, I want to display it as 210.5k, if the value is in the millions, e.g. 2,120,000, I want to display it as 2.12m
console.log(formatValue(210500))
console.log(formatValue(2120000))
console.log(formatValue(675000))<script src="https://cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js"></script>答案#1
在这种情况下,您需要根据原始数字的大小使用不同的格式字符串。看起来您有以下几种情况:
- 如果数字小于1000,则返回相同的数字的长格式,但最多保留两位小数。
- 如果数字在1000到10,000之间,则以长格式返回相同的数字,并且不显示小数位。
- 如果数字在10,000到1,000,000之间,请以简写格式返回相同的数字,最多保留一位小数。
- 如果数字大于1,000,000,则以简写格式返回相同的数字,最多保留两位小数。
对于每种情况,你都需要一个不同的格式字符串。你可以通过将数字与每个阈值进行比较,并根据它的大小设置格式字符串来实现。
function formatValue(value, shorthandFormat = true, shorthandLength = 5) {
if (value === undefined || value === null) return '?';
let valueString = value.toString();
if (valueString.trim() === '') return '';
let numeralValue = numeral(value)
// Note the format changes depending on how large the value is.
let formatter = "0[.][00]" // Default formatter: returns the same number with at most, two decimals.
if (value > 1000) formatter = "0" // Over 1000: remove any decimal part.
if (value > 10000) formatter = "0.[0]a" // Over 10000: use shorthand with at most, one decimal.
if (value > 1000000) formatter = "0.[00]a" // Over 1000000: use shorthand with at most, two decimals.
let formattedValue = numeralValue.format(formatter);
return formattedValue;
}
const tests = [
// Small numbers contain at most, two decimals.
[0, "0"],
[1, "1"],
[1.1, "1.1"],
[1.11, "1.11"],
[1.115, "1.12"],
[11.1, "11.1"],
[11.11, "11.11"],
[16.75, "16.75"],
[675, "675"],
[675.5, "675.5"],
[675.55, "675.55"],
// Numbers between one-thousand and ten-thousand may not contain decimals.
[6700.05, "6700"],
[2522.25, "2522"],
[6000, "6000"],
// Numbers between ten-thousand and one-million should use shorthand, with at most one decimal.
[67500.89, "67.5k"],
[67530.85, "67.5k"],
[210500, "210.5k"],
[210000, "210k"],
// Numbers greater than one-million should use shortand, with at most two decimals.
[2120000, "2.12m"],
[6750000, "6.75m"],
[2000000, "2m"],
[2100000, "2.1m"],
[2010000, "2.01m"],
[2001000, "2m"],
]
tests.forEach(([input, output]) => console.log(`${formatValue(input) === output ? "PASS" : "FAIL"}: ${input} --> ${formatValue(input)}. Expected: ${output}`));<script src="https://cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js"></script>注意:数值 67500.89 的测试已更改为期望结果为 67.5k,因为 6.7k 似乎是笔误。
答案#2
这是我前些时候写的一个数字简写格式化器的代码示例,它正好能实现你想要的功能。
function numberIntoString({
value,
decimals,
}) {
value = value.toString().replace(/[^0-9.]/g, "");
let si = [
{ value: 1e3, symbol: "K" },
{ value: 1e6, symbol: "M" },
{ value: 1e9, symbol: "B" },
{ value: 1e12, symbol: "T" },
];
let i;
for (i = si.length - 1; i > 0; i--) {
if (value >= si[i].value) {
break;
}
}
return (
(value / si[i].value)
.toFixed(decimals)
.replace(/\.0+$|(\.[0-9]*[1-9])0+$/, "$1") + si[i].symbol
);
}
