Advanced-Frontend/Daily-Interview-Question

第 143 题:将'10000000000'形式的字符串,以每3位进行分隔展示'10.000.000.000',多种实现方式

zhoushaw opened this issue · 56 comments

第 143 题:将'10000000000'形式的字符串,以每3位进行分隔展示'10.000.000.000',多种实现方式

var str = '10000000000';
var arr = [];
for(var i=0; i<Math.round(a.length/3); i++){
arr.push(str.substring(str.length-3*(i+1), str.length-i*3));
}
arr.reverse();
arr.join('.')

const splitStr = (str, point = 3, split = '.') => {
    let newStr = '';
    const reverseStr = str.split('').reverse().join('');
    for (const s in reverseStr) {
        newStr = (s !== '0' && s % point === 0) ? newStr + split + reverseStr[s] : newStr + reverseStr[s];
    }
    return newStr.split('').reverse().join('');
}
lhyt commented

如果一行写不出来,我选择不写

// 德国以 . 分割金钱, 转到德国当地格式化方案即可
10000000000..toLocaleString('de-DE') 

// 寻找字符空隙加 .
'10000000000'.replace(/\B(?=(\d{3})+(?!\d))/g, '.')

// 寻找数字并在其后面加 . 
'10000000000'.replace(/(\d)(?=(\d{3})+\b)/g, '$1.')

var myNum = Number('10000000000'); //字符串转数字后就可以使用toLocaleString()啦~

var num2Str = myNum .toLocaleString(); //"10,000,000,000"

num2Str.replace(/,/g, "."); //"10.000.000.000"

哭了,这么好的方法竟然这么多人踩

应该是考金额的转换吧,考虑到小数点的情况,如下:
'10000000000.0000'.replace(/\d{1,3}(?=(\d{3})+(.\d*)?$)/g, '$&,')

笨方法

function addCommaIntoStringNumber(sNumber, splitNumber = 3){
  if (sNumber.length <= splitNumber) {
      return sNumber
  }
  let result = []
  let sNumberQuene = sNumber.split('')
  let index = 1
  let sNumberLength = sNumber.length
  while(sNumberLength--) {
    result.unshift(sNumberQuene.pop())
    if (index++ === splitNumber) {
        result.unshift(',')
        index = 1
    }
  }
  return result.join('')

}

类似金额的转化,这里相对还要简单一些
'10000000000'.replace(/(?!^)(?=(\d{3})+$)/g, '.');
(?!^)的目的是不匹配开头,虽然这里刚好不会匹配到开头;
但是可以不增加(?!^)试试字符串'100000000000'

如果主要想考数字的千位分隔符表示法,可以使用正则
var str= '10000000000';
var reg=/(?!^)(?=(\d{3})+$)/g;
str.replace(reg, '.') // "10.000.000.000"

str.split("").reverse().reduce((prev, cur, index) => (index + 1) % 3 == 0 ? '.' + cur + prev : cur + prev)
// 正则不大会...只好一步步来
  function foo(num) {
    const arr = [...num].reverse();
    const rst = arr.reduce((init, ele, i) => {
      i % 3 === 2 ? init.push(ele, '.') : init.push(ele);
      return init;
    }, []);
    return rst.reverse().join('')
  }
//  保留两位小数后添加千分位符
 getEffective = str => {
        let [int, decimal] = String(Number(str).toFixed(2)).split('.')
        let res =
          [...int]
            .reverse()
            .reduce(
              (prev, item, index) => (
                prev.push(index % 3 === 2 ? ',' + item : item), prev
              ),
              []
            )
            .reverse()
            .join('') + `.${decimal}`
        if (res[0] === ',') {
          return res.slice(1)
        }
        return res
      }

var str= '10000000000';
new Intl.NumberFormat().format(str);
// "10,000,000,000"

"1000000000000".split('').reverse().reduce((total, each, i)=>{
        total.push(each)
        if ((i + 1) % 3 == 0) total.push('.')
        return total
}, []).reverse().join('')
wmui commented
new Intl.NumberFormat().format(100000000000).replace(/,/g, '.');
console.log('100000000000'.replace(/(?!^)(?=(\d{3})+$)/g,','))
const getStr=(str,splitNum=3,split=',')=>{
    return str.split('').reverse().map((v,i)=>{
            if(i&&i%splitNum==0){
                return `${v}${split}`
            }
            return v
    }).reverse().join('');
}

getStr('10000000000',3,',');
var reg = /(\B)(?=(\d{3})+$)/g;
console.log("1000000000".replace(reg, '.'));  // 1.000.000.000

'10000000000'.replace(/(?!^)(?=(\d{3})+$)/g,'.')

str.split("").reverse().reduce((prev, cur, index) => (index + 1) % 3 == 0 ? '.' + cur + prev : cur + prev) 上面没有考虑索引+1正好等于长度的时候. 此题str多加一个字符串就会有问题
image

str.replace(/\d(?=(\d{3})+$)/g, '$&.');

"1000000000000".split('').reverse().reduce((total, each, i)=>{
        total.push(each)
        if ((i + 1) % 3 == 0) total.push('.')
        return total
}, []).reverse().join('')

有没有考虑到1刚好可以除尽的情况, 就会 .100.000.000.00

如果一行写不出来,我选择不写

// 德国以 . 分割金钱, 转到德国当地格式化方案即可
10000000000..toLocaleString('de-DE') 

// 寻找字符空隙加 .
'10000000000'.replace(/\B(?=(\d{3})+(?!\d))/g, '.')

// 寻找数字并在其后面加 . 
'10000000000'.replace(/(\d)(?=(\d{3})+\b)/g, '$1.')

哪位大神能帮忙解释一下第一种方法为什么有两个点..

如果一行写不出来,我选择不写

// 德国以 . 分割金钱, 转到德国当地格式化方案即可
10000000000..toLocaleString('de-DE') 

// 寻找字符空隙加 .
'10000000000'.replace(/\B(?=(\d{3})+(?!\d))/g, '.')

// 寻找数字并在其后面加 . 
'10000000000'.replace(/(\d)(?=(\d{3})+\b)/g, '$1.')

哪位大神能帮忙解释一下第一种方法为什么有两个点..

因为数字后面接第一个.是会被认为是小数点的,所以就变成了10000000. 之后连接一个toLocaleString('de-DE') ,接第二个点才被认为是对这个数字字面量进行操作。

let str = '1000000000000'

let result = [...str].reverse().map( (v, i) => {
  if (i % 3 === 0 && i !== 0) {
    return `${v}.`
  }
  return v
}).reverse().join("")

g, "."); //"10.000.000.000"

应该是酸你想得出来自己想不出来所以就踩了哈哈

'10000000'.replace(/(?!^)(?=(\d{3})+$)/g, '.')

Number('1000000000').toLocaleString().replace(/,/g, '.')

不会正则就用粗旷的方式吧

'1000000000000'.split('').reverse().map((v,i)=>{
  return i%3==2?`,${v}`:v
}).reverse().join('')
// 正则不大会...只好一步步来
  function foo(num) {
    const arr = [...num].reverse();
    const rst = arr.reduce((init, ele, i) => {
      i % 3 === 2 ? init.push(ele, '.') : init.push(ele);
      return init;
    }, []);
    return rst.reverse().join('')
  }

'100000000'会输出'.100.000.000'
还需要加个判断 i % 3 === 2&&i!==(arr.length-1) ? init.push(ele, '.') : init.push(ele);

let reg = /(?!^)(?=(\d{3})+$)/g
'10000000000'.replace(reg, ',')

Number(100000000000).toLocaleString('de-DE')

87463297 =>"87,463,297"
    "87463297".replace(  /\d{1,3}(?=(\d{3})+$)/g  ,  (s)=>s+',')
        /\d{1,3}(?=(\d{3})+$)/g ,//找出后面跟有三个数字的,即["87", "463"],添加逗号在后面即可
            \d{1,3} //1-3位数字
            (?=(\d{3})+$) //?=表示后面要跟着符合(\d{3})+$的, 即1个或多个(3个数字)结尾的
// 从后向前遍历,每次截取三个字符,直到完成
const str = '10000000000';
const arr = [];
for (let len = str.length, i = len - 1; i >= 0; i = i - 3) {
  let start = i - 2;
  if (start < 0) start = 0;
  arr.push(str.slice(start, i + 1));
}
return arr.reverse().join('.');

'10000000000.0000'.replace(/\d{1,3}(?=(\d{3})+(.\d*)?$)/g, '$&,')

笑死我了,运行过吗?

str.split("").reverse().reduce((prev, cur, index) => (index + 1) % 3 == 0 ? '.' + cur + prev : cur + prev)

有点问题
'100000000'.split("").reverse().reduce((prev, cur, index) => (index + 1) % 3 == 0 ? '.' + cur + prev : cur + prev)
=> //".100.000.000"

const thousandSeparator = (num) => {
  let tstr = num.toString()
  let res = ''
  let count = 0
  for (let i = tstr.length - 1; i >= 0; i--) {
    res += tstr[i]
    ++count
    if (count % 3 === 0 && i !== 0) {
      res += '.'
    }
  }
  res = res.split('').reverse().join('')
  return res
}

考虑符号和小数位,用的笨办法

const thousands = (num) => {
  let suff;
  let pre;
  let symbol='';
  if(num){
    num = num +'';
    [pre,suff] = num.split('.')
    if(pre.length <= 3) return num;
    if(isNaN(pre.slice(0,1))){
      symbol = pre.slice(0,1);
      pre = pre.slice(1);
    }
    pre = pre.split('').reverse();
    for(let i in pre){
      if(i>1 && i%3 === 0){
        pre[i] = pre[i]+',';
      }
    }
    return symbol+pre.reverse().join('')+(suff ? ('.'+suff):'');
  }
  return num;
}
const regex = /(?<!^)(?=(\d{3})+$)/g;
const s = '123456789';
s.replace(regex, ',');
/**
 * @param {String} str
 * @return {String}
 */
function separate(str) {
  const arr = str.split('')
  for (let i = arr.length - 3; i > 0; i -= 3) {
    arr[i] = `.${arr[i]}`
  }
  return arr.join('')
}

const res = separate('100000000')
console.log('res: ', res)

'10000000000'
.split('')
.reverse()
.join('')
.replace(/(\d{3})/g,'$1.')
.split('')
.reverse()
.join('')

Number('100000000').toLocaleString()

"1000000000000".split('').reverse().reduce((total, each, i)=>{
        total.push(each)
        if ((i + 1) % 3 == 0) total.push('.')
        return total
}, []).reverse().join('')

有没有考虑到1刚好可以除尽的情况, 就会 .100.000.000.00

可以这么写
"1000000000000".split("").reverse().reduce((prev, next, index) => {
if(index > 0 && index % 3 == 0) {
return next = next + '.' + prev
} else {
return next + prev
}
}, '')

"1000000000000".split("").reverse().reduce((prev, next, index) => {
if(index > 0 && index % 3 == 0) {
return next = next + '.' + prev
} else {
return next + prev
}
}, '')
XW666 commented

const fond07 = (str) => {
let defaultStr = ''
if (str !== null && str !== '' && str !== undefined) {
defaultStr = str.replace(/(\d)(?=(\d{3})+\b)/g, '$1.')
}
return defaultStr
}

考虑数字是三的倍数情况

function splitNum(str) {
    return str.replace(/(\d)(?=(\d{3})+$)/g, '$1.');
  }
const transStr = str => str.split('')
                       .reduceRight((result, word, index, arr) => 
                                         ((index + 1) % 3 === 0  && index !== arr.length - 1  ?  '.'  :  '' ) 
                                         + word + result)
function format(str) {
  const reverse = str.toString().split('').reverse().join('');
  return reverse.replace(/(\d{3})/g, '$1,').replace(/\,$/g, '').split('').reverse().join('');
}

'-1019234801211.2142345678'.replace(/(?<!...)(\d)(?=(\d{3})+($|.))/g, '$1,')

ts的实现方法:

方法一(推荐):

type SplitStr<
  Str extends string,
  Ele extends string = '.'
> = Str extends `${infer First}${infer Second}${infer Third}${infer Rest}`
      ? `${First}${Second}${Third}${Ele}${SplitStr<Rest>}`
      : Str

type ReverseStr<
  Str extends string,
  Result extends string = ''
> = Str extends `${infer First}${infer Rest}`
      ? ReverseStr<Rest , `${First}${Result}`>
      : Result

type test= ReverseStr<SplitStr<ReverseStr<'10000000000'>>>

let a:test = '10.000.000.000'   //代码提示即为所求结果

方法二:

type SplitStr<
  Arr extends string,
  Ele extends string = '.',
  LimitLength extends number = 3, 
> = Arr extends `${infer First}${infer Second}${infer Rest}` | `${infer Left}${infer Right}`
  ? Divide<Subtract<StrLen<Arr> , 1> , LimitLength> extends never
    ? Divide<Subtract<StrLen<Arr> , 2> , LimitLength> extends never
      ? AddPoint<Arr , Ele>
      : `${First}${Second}${Ele}${AddPoint<Rest>}`
    : `${Left}${Ele}${AddPoint<Right>}`
  : never

type AddPoint<
  Str extends string ,
  Ele extends string = '.'
> = Str extends `${infer First}${infer Second}${infer Third}${infer Rest}`
      ? StrLen<Rest> extends 0
        ? Str
        : `${First}${Second}${Third}${Ele}${AddPoint<Rest , Ele>}`
      : Str

type BuildArray<
  Length extends number,
  Ele = unknown,
  Arr extends unknown[] = []
> = Arr['length'] extends Length
      ? Arr
      : BuildArray<Length , Ele , [...Arr , Ele]>

type Subtract<Num1 extends number , Num2 extends number> = 
  BuildArray<Num1> extends [...arr1: BuildArray<Num2> , ...arr2: infer Rest]
    ? Rest['length']
    : never

type Divide<
  Num1 extends number,
  Num2 extends number,
  CountArr extends unknown[]=[]
> = Num1 extends 0? CountArr['length']
    : Divide<Subtract<Num1, Num2> , Num2 , [unknown, ...CountArr]>

type StrLen<
  Str extends string,
  CountArr extends unknown[]=[]
> = Str extends `${string}${infer Rest}`
    ? StrLen<Rest , [...CountArr , unknown]>
    : CountArr['length']

type test = SplitStr<'10000000000'>

let a:test = '10.000.000.000'   //代码提示即为所求结果

正则

'10000000000'.replace(/(\d)(?=(\d{3})+$)/g, '$1.')

国际化

new Intl.NumberFormat('de-DE').format(100000000000)

toLocaleString

100000000000..toLocaleString('de-DE')
xuhen commented
function format(str) {
    let result = '';
    const len = str.length;
    const total = len - 1;
   // 从右往左遍历
    for (let i = total; i >= 0; i--) {
        if (total - i > 0 && (total - i) % 3 === 0) {
            result = str[i] + '.' + result;
        } else {
            result = str[i] + result;
        }
    }
    return result;
}
'10000000000'.replace(/\d(?=(\d{3})+$)/g, '$&.')

'10000000000'.replace(/(\d)(?=(\d{3})+$)/g, '$1.')
// 结果是: '10.000.000.000'

function format(str) {
  return str
    .split('')
    .reverse()
    .reduce((acc, cur, index) =>
      index % 3 === 0 ? `${cur}.${acc}` : cur + acc
    );
}

递归
function transStr(str) {
return str.length > 3 ? transStr(str.slice(0, -3)) + "." + str.slice(-3) : str;
}