在JavaScript中将长数字转换为缩写字符串,具有特殊的短缺要求

Phi*_*sen 59 javascript numbers

在JavaScript中,如何编写一个函数将给定的[编辑:正整数 ]数字(低于1000亿)转换为3个字母的缩写 - 其中0-9和az/AZ计为字母,但是点(因为它在许多比例字体中如此微小)不会,并且在字母限制方面会被忽略?

这个问题与这个有用的线程有关,但它不一样; 例如,那个函数将转向例如"123456 - > 1.23k"("123.5k"是5个字母)我正在寻找做"123456 - > 0.1m"("0 [.] 1m"为3个字母的东西).例如,这将是希望函数的输出(左原始,右理想返回值):

0                      "0"
12                    "12"
123                  "123"
1234                "1.2k"
12345                "12k"
123456              "0.1m"
1234567             "1.2m"
12345678             "12m"
123456789           "0.1b"
1234567899          "1.2b"
12345678999          "12b"
Run Code Online (Sandbox Code Playgroud)

谢谢!

更新:谢谢!在做出以下修改时,答案在于并按照要求运作:

function abbreviateNumber(value) {
    var newValue = value;
    if (value >= 1000) {
        var suffixes = ["", "k", "m", "b","t"];
        var suffixNum = Math.floor( (""+value).length/3 );
        var shortValue = '';
        for (var precision = 2; precision >= 1; precision--) {
            shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
            var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
            if (dotLessShortValue.length <= 2) { break; }
        }
        if (shortValue % 1 != 0)  shortValue = shortValue.toFixed(1);
        newValue = shortValue+suffixes[suffixNum];
    }
    return newValue;
}
Run Code Online (Sandbox Code Playgroud)

chu*_*tor 51

我相信ninjagecko的解决方案并不完全符合您的标准.以下功能可以:

function intToString (value) {
    var suffixes = ["", "k", "m", "b","t"];
    var suffixNum = Math.floor((""+value).length/3);
    var shortValue = parseFloat((suffixNum != 0 ? (value / Math.pow(1000,suffixNum)) : value).toPrecision(2));
    if (shortValue % 1 != 0) {
        var shortNum = shortValue.toFixed(1);
    }
    return shortValue+suffixes[suffixNum];
}
Run Code Online (Sandbox Code Playgroud)

对于大于99万亿的值,不会添加任何字母,可以通过附加到'suffixes'数组轻松修复.

Philipp编辑如下:通过以下更改,它完全符合所有要求!

function abbreviateNumber(value) {
    var newValue = value;
    if (value >= 1000) {
        var suffixes = ["", "k", "m", "b","t"];
        var suffixNum = Math.floor( (""+value).length/3 );
        var shortValue = '';
        for (var precision = 2; precision >= 1; precision--) {
            shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
            var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
            if (dotLessShortValue.length <= 2) { break; }
        }
        if (shortValue % 1 != 0)  shortNum = shortValue.toFixed(1);
        newValue = shortValue+suffixes[suffixNum];
    }
    return newValue;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果(shortValue%1!= 0)shortNum = shortValue.toFixed(1);末尾@PhilippLenssen的编辑中未定义`shortNum`。 (2认同)

D.D*_*iso 28

这也处理非常大的值,并且更简洁和有效.

abbreviate_number = function(num, fixed) {
  if (num === null) { return null; } // terminate early
  if (num === 0) { return '0'; } // terminate early
  fixed = (!fixed || fixed < 0) ? 0 : fixed; // number of decimal places to show
  var b = (num).toPrecision(2).split("e"), // get power
      k = b.length === 1 ? 0 : Math.floor(Math.min(b[1].slice(1), 14) / 3), // floor at decimals, ceiling at trillions
      c = k < 1 ? num.toFixed(0 + fixed) : (num / Math.pow(10, k * 3) ).toFixed(1 + fixed), // divide by power
      d = c < 0 ? c : Math.abs(c), // enforce -0 is 0
      e = d + ['', 'K', 'M', 'B', 'T'][k]; // append power
  return e;
}
Run Code Online (Sandbox Code Playgroud)

结果:

for(var a='', i=0; i < 14; i++){ 
    a += i; 
    console.log(a, abbreviate_number(parseInt(a),0)); 
    console.log(-a, abbreviate_number(parseInt(-a),0)); 
}

0 0
-0 0
01 1
-1 -1
012 12
-12 -12
0123 123
-123 -123
01234 1.2K
-1234 -1.2K
012345 12.3K
-12345 -12.3K
0123456 123.5K
-123456 -123.5K
01234567 1.2M
-1234567 -1.2M
012345678 12.3M
-12345678 -12.3M
0123456789 123.5M
-123456789 -123.5M
012345678910 12.3B
-12345678910 -12.3B
01234567891011 1.2T
-1234567891011 -1.2T
0123456789101112 123.5T
-123456789101112 -123.5T
012345678910111213 12345.7T
-12345678910111212 -12345.7T
Run Code Online (Sandbox Code Playgroud)

  • 更好的解决方案 (2认同)

Jam*_* L. 12

现代、简单、内置、高度可定制和“无代码”的方式:Intl.FormatNumber格式函数(兼容性图

var numbers = [98721, 9812730,37462,29,093484620123, 9732,0283737718234712]
for(let num of numbers){
  console.log(new Intl.NumberFormat( 'en-US', { maximumFractionDigits: 1,notation: "compact" , compactDisplay: "short" }).format(num));
}
98.7K
9.8M
37.5K
29
93.5B
9.7K
283.7T
Run Code Online (Sandbox Code Playgroud)

笔记:


小智 11

我想你不能尝试这个数字/

如果你想转换1000到1K

console.log(numeral(1000).format('0a'));
Run Code Online (Sandbox Code Playgroud)

如果你想转换123400到123.4k试试这个

console.log(numeral(123400).format('0.0a'));
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法在数字为 1000 时使用“0.0a”但显示“1k”而不是“1.0k”?(修剪零) (5认同)

NuS*_*ler 8

这是我认为相当优雅的解决方案.它不会尝试处理负数:

const COUNT_ABBRS = [ '', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' ];

function formatCount(count, withAbbr = false, decimals = 2) {
    const i     = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000));
    let result  = parseFloat((count / Math.pow(1000, i)).toFixed(decimals));
    if(withAbbr) {
        result += `${COUNT_ABBRS[i]}`; 
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

示例:

   formatCount(1000, true);
=> '1k'
   formatCount(100, true);
=> '100'
   formatCount(10000, true);
=> '10k'
   formatCount(10241, true);
=> '10.24k'
   formatCount(10241, true, 0);
=> '10k'
   formatCount(10241, true, 1)
=> '10.2k'
   formatCount(1024111, true, 1)
=> '1M'
   formatCount(1024111, true, 2)
=> '1.02M'
Run Code Online (Sandbox Code Playgroud)

  • 这并没有解决提出的问题,但它正是_I_正在寻找的东西.谢谢. (5认同)

tfm*_*gue 7

使用Math对象,映射对象,for循环等,此线程上的许多答案变得相当复杂。但是这些方法实际上并没有真正改善设计-它们引入了更多的代码行,更多的复杂性和更多的内存开销。在评估了几种方法之后,我认为手动方法最容易理解,并且性能最高。

const formatCash = n => {
  if (n < 1e3) return n;
  if (n >= 1e3 && n < 1e6) return +(n / 1e3).toFixed(1) + "K";
  if (n >= 1e6 && n < 1e9) return +(n / 1e6).toFixed(1) + "M";
  if (n >= 1e9 && n < 1e12) return +(n / 1e9).toFixed(1) + "B";
  if (n >= 1e12) return +(n / 1e12).toFixed(1) + "T";
};

console.log(formatCash(1235000));
Run Code Online (Sandbox Code Playgroud)


nin*_*cko 6

根据我在回答/sf/answers/742034401/,你的回答实际上是略短来实现,通过使用.substring(0,3):

function format(n) {
    with (Math) {
        var base = floor(log(abs(n))/log(1000));
        var suffix = 'kmb'[base-1];
        return suffix ? String(n/pow(1000,base)).substring(0,3)+suffix : ''+n;
    }
}
Run Code Online (Sandbox Code Playgroud)

(像往常一样,除非你确切地知道你正在做什么,否则不要使用数学;分配var pow=...等会导致疯狂的错误.请参阅链接以获得更安全的方法.)

> tests = [-1001, -1, 0, 1, 2.5, 999, 1234, 
           1234.5, 1000001, Math.pow(10,9), Math.pow(10,12)]
> tests.forEach(function(x){ console.log(x,format(x)) })

-1001 "-1.k"
-1 "-1"
0 "0"
1 "1"
2.5 "2.5"
999 "999"
1234 "1.2k"
1234.5 "1.2k"
1000001 "1.0m"
1000000000 "1b"
1000000000000 "1000000000000"
Run Code Online (Sandbox Code Playgroud)

如果您对3个字符的要求严格,则需要捕获结果> = 1万亿的情况,否则您可能会创建损坏的数据,这将非常糟糕.

  • 很好的解决方案。也疯狂支持使用已弃用的“with”语句:) (2认同)

dan*_*woz 5

代码

const SI_PREFIXES = [
  { value: 1, symbol: '' },
  { value: 1e3, symbol: 'k' },
  { value: 1e6, symbol: 'M' },
  { value: 1e9, symbol: 'G' },
  { value: 1e12, symbol: 'T' },
  { value: 1e15, symbol: 'P' },
  { value: 1e18, symbol: 'E' },
]

const abbreviateNumber = (number) => {
  if (number === 0) return number

  const tier = SI_PREFIXES.filter((n) => number >= n.value).pop()
  const numberFixed = (number / tier.value).toFixed(1)

  return `${numberFixed}${tier.symbol}`
}

abbreviateNumber(2000) // "2.0k"
abbreviateNumber(2500) // "2.5k"
abbreviateNumber(255555555) // "255.6M"
Run Code Online (Sandbox Code Playgroud)

测试:

import abbreviateNumber from './abbreviate-number'

test('abbreviateNumber', () => {
  expect(abbreviateNumber(0)).toBe('0')
  expect(abbreviateNumber(100)).toBe('100')
  expect(abbreviateNumber(999)).toBe('999')

  expect(abbreviateNumber(1000)).toBe('1.0k')
  expect(abbreviateNumber(100000)).toBe('100.0k')
  expect(abbreviateNumber(1000000)).toBe('1.0M')
  expect(abbreviateNumber(1e6)).toBe('1.0M')
  expect(abbreviateNumber(1e10)).toBe('10.0G')
  expect(abbreviateNumber(1e13)).toBe('10.0T')
  expect(abbreviateNumber(1e16)).toBe('10.0P')
  expect(abbreviateNumber(1e19)).toBe('10.0E')

  expect(abbreviateNumber(1500)).toBe('1.5k')
  expect(abbreviateNumber(1555)).toBe('1.6k')

  expect(abbreviateNumber(undefined)).toBe('0')
  expect(abbreviateNumber(null)).toBe(null)
  expect(abbreviateNumber('100')).toBe('100')
  expect(abbreviateNumber('1000')).toBe('1.0k')
})
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

29034 次

最近记录:

5 年,11 月 前