解锁实现数值千分位的4种方式🔓

123 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

1、数值转字符串遍历拼接

实现思路

  1. 数字转字符串,字符串按照 '. '进行分隔(因为有可能是小数)
  2. 整数部分变为字符串数组并进行倒叙
  3. 遍历该数组,每3位添加一个逗号
  4. 拼接整数部分与小数部分
// 1938765432.71  -> 1,938,765,432.71
function format_with_array(number) {
  // 将数字分隔成整数部分与小数部分 [1938765432, 71]
  const arr = (number + "").split(".");
  // 将整数部分的数字分割成字符串数组 
  // 1938765432 -> ['1','9','3','8','7','6','5','4','3','2']
  const ints = arr[0].split("");
  // 小数部分
  const fraction = arr[1] || "";
  let result = "";
  ints.reverse().forEach((val, i) => {
    // 非第一位并且是位值是3的倍数添加 ","
    // 依次是 2 + ''3 + '2'4 + '32'5 + ','+ '432'...
    if (i !== 0 && i % 3 === 0) {
      result = val + "," + result;
    } else {
      result = val + result;
    }
  });
  // 1,938,765,432 + '.' + 71 -> 1,938,765,432.71
  return result + (!!fraction ? "." + fraction : "");
}
console.log(format_with_array(1938765432.71));

2、字符串+substring截取

实现思路

  1. 数字转字符串,并按照'.'分隔
  2. 整数部分对3求模,获取多余的部分
  3. 按照长度3进行截取,并添加','
  4. 拼接整数部分与小数部分
function format_with_substring(number) {
  // 分隔整数部分与小数部分
  const arr = (number + "").split(".");
  // 取出整数部分的字符串,方便通过substring进行截取
  const int = arr[0];
  // 取出小数部分以便最后进行拼接
  const fraction = arr[1] || "";

  // 获取多余位数,有可能是0
  const more = int.length % 3;
  // 截取出多余出来的字符串,如果more是0则此时截取出来的result为空字符串
  let result = int.substring(0, more);
  for (let i = 0; i < Math.floor(int.length / 3); i++) {
    // 每次循环需要从多余位数后面开始截取3个并追加逗号
    result += "," + int.substring(more + i * 3, more + (i + 1) * 3);
  }
  // 如果多余出来0个数字,那么需要去除开头多拼接的逗号
  if (more === 0) {
    result = result.substring(1);
  }
  return result + (!!fraction ? "." + fraction : "");
}
console.log(format_with_substring(1938765432.71)); // 1,938,765,432.71

3、除法 + 求模

实现思路

  1. 数值对1000进行求模,获得最高三位
  2. 值除以1000,将值是否大于1作为判定是否结束的条件
  3. 重复1、2步骤
  4. 拼接整数部分与小数部分
function format_with_mod(number) {
  let n = number;
  let result = "";
  let temp;
  do {
    // 求模的值,用于获取高三位,这里可能有小数
    mod = n % 1000;
    // 值是不是大于1,是继续的条件
    n = n / 1000;
    // 由于可能为小数,所以要通过~~变为整数
    temp = ~~mod;
    // 要注意这里要对temp进行填充,比如1002取模后,temp为2,此时要填充为002
    // 不进行填充的话1002最后会变成1,2而不是1,002
    result =
      (n >= 1 ? `${temp}`.padStart(3, "0") : temp) +
      (!!result ? "," + result : "");
  } while (n >= 1);

  const strNumber = number + "";
  const index = strNumber.indexOf(".");
  // 拼接小数部分,
  if (index >= 0) {
    result += strNumber.substring(index);
  }
  return result;
}
console.log(format_with_mod(1002)); // 1,002

4、正则表达式

正则表达式中的先行断言、后行断言、正向否定查找与反向否定查找:

名称表达式作用
先行断言(前瞻)exp1(?=exp2)查找exp2前面的exp1
后行断言(后顾)(?<=exp2)exp1查找exp2后面的exp1
正向否定查找(负前瞻)exp1(?!exp2)查找后面不是exp2的exp1
反向否定查找(负后顾)(?<!exp2)exp1查找前面不是exp2的exp1

(更多正则表达式有关知识详见文章:正则表达式

实现思路

利用正则表达式的先行断言,去匹配每3个数字为一组的前面的数字,在所匹配内容后面加上','逗号

function format_with_regex(number) {
  const reg = /\d{1,3}(?=(\d{3})+$)/g;
  const arr = (number + "").split(".");
  const fraction = arr[1] || "";
  // $&表示匹配到的每组内容
  let result =  arr[0].replace(reg, '$&,');
  return fraction ? result + "." + fraction : result;
}

// replace第二个参数也可以传入一个回调函数,其中回调函数第一个参数表示匹配到的内容
function format_with_regex2(number) {
  const reg = /\d{1,3}(?=(\d{3})+$)/g;
  const arr = (number + "").split(".");
  const fraction = arr[1] || "";
  let result = arr[0].replace(reg, function (match) {
    return match + ",";
  });
  return fraction ? result + "." + fraction : result;
}