记一次bug解决过程(数字转化成中文)

栏目: JavaScript · 发布时间: 6年前

内容简介:由于公司业务周期较短,时常是几个项目一起做,或是加上bug修复。上午的时候接到个任务,正式上的网站发现如下图的错误。找到项目中对应页面,很快发现了问题,原来之前的哥们通过定义了个数组,通过序号来取对应的中文。这样的方式缺点很明显,个数有限。导致现在出现不够用的状况。经过考虑觉得可以抽出一个公共的方法代码如下:

由于公司业务周期较短,时常是几个项目一起做,或是加上bug修复。上午的时候接到个任务,正式上的网站发现如下图的错误。

记一次bug解决过程(数字转化成中文)

问题原因

找到项目中对应页面,很快发现了问题,原来之前的哥们通过定义了个数组,通过序号来取对应的中文。这样的方式缺点很明显,个数有限。导致现在出现不够用的状况。

记一次bug解决过程(数字转化成中文)
记一次bug解决过程(数字转化成中文)

解决方式

经过考虑觉得可以抽出一个公共的方法代码如下:

/**
 * 根据输入的数字返回对应是中文,格式如:三十一
 *  @param {Number} index 序号
 */
export function covertNumberTochinese(index) {
  const multiple = parseInt((index + 1) / 10)
  const remainder = (index + 1) % 10
  const weekheadNum = [
    '一',
    '二',
    '三',
    '四',
    '五',
    '六',
    '七',
    '八',
    '九',
    '十'
  ]
  let text = ''
  const textMap = new Map([
    [/^1_[0-9]$/, () => `十${weekheadNum[remainder - 1]}`],
    [/^1_0$/, () => `十`],
    [
      /^[2-9]_[1-9]$/,
      () => `${weekheadNum[multiple - 1]}十${weekheadNum[remainder - 1]}`
    ],
    [/^[2-9]_0$/, () => `${weekheadNum[multiple - 1]}十`],
    [/^0_\w/, () => `${weekheadNum[remainder - 1]}`]
  ])
  const textList = [...textMap].filter(([reg]) => {
    return reg.test(multiple + '_' + remainder)
  })
  textList.forEach(([reg, callBack]) => {
    text = callBack()
  })
  return text
}
复制代码
  1. multiple用来判断有几个10,remainder表示余几。
  2. 这里使用Map数据结构的原因是因为将对象作为键名,这样可以将正则与函数关联起来。
  3. 使用正则匹配,可以匹配多种情况,使用正则的test方法来校验是否匹配成功。

需要用到的知识点

  1. new Map([['键名':'键值']])
  2. ... 扩展运算符 遍历 Iterator 接口(这里是Map)
  3. [reg] = [/^1_[0-9]$/, () => `十${weekheadNum[remainder - 1]}`] 数组结构赋值

分析

  1. covertNumberTochinese函数接受一个数值,对数值进行取余 remainder(用来当作个位数)和商取整的multiple(用来当作十位数)。
  2. 将个位数十位数拼接成用_相连的字符串,然后用正则取匹配这个字符串。然后两个中文字拼接起来。
  3. 需要注意的是当multiple为1,remainder为0时本应该返回'十零'但是我们习惯不是注意的叫法,多加一个判断条件。
  4. 判断下remainder(个位数)为0时,省去'几十零'后面的零

小结

用上面的方法可以将数字匹配到中午 1-99位,虽然项目中是够用了,但是局限性还是很大,而且判断的条件很多,逻辑不直观。

寻求其他解决方案

/**
 * 根据输入的数字返回对应是中文,格式如:一千零一
 *  @param {Number|String} index 序号或者数字开头的字符串
 */
  export numberToChinese(number) {
      number = String(parseInt(number))
      const ChineseText = '零一二三四五六七八九'
      const smallUnit = '十百千'
      const length = number.length
      let n = length - 2
      let string = ''
      for (var i = 0; i < length; i++) {
        let num = number.charAt(i)
        string += ChineseText.charAt(num)
        string += num > 0 ? smallUnit.charAt(n) : ''
        n--
      }
      return string
    }
复制代码

分析

  1. 首先将传入的数字取整处理,然后将其转换成字符串,为了是使用字符串的 .charAt 方法取对应位数的中文。
  2. 定义好中文的0-9,以及单位'十百千' (为了简单起见,只讨论 四位数以下 的转换,位数增加方法是类似的)
  3. 定义好string是最终返回的中文字符串,是通过 拼接 的方式得到一个中文的数字,这里n代表取第几位单位也就是取 smallUnit 的第几位

循环体中做的事

  1. 去除number(也就是数字字符串如1001)的第一位,就是数字1类型是string类型,然后通过这个1取 ChineseText 中的中文得到中文的一
  2. 然后通过n取一对应的单位,这里n=length-2是因为再定义单位时是 从十开始 的而不是从个位数开始,并且.charAt(0) 取的是字符串的第一位 。并且当数字为零的时候不需要单位,所以加了num > 0的限定条件。

完善

就此数字转换成中文的方法就写完了,在浏览器中打印如下

记一次bug解决过程(数字转化成中文)

有多个零的时候我们习惯是一千零一,并且结尾为零的时候是省略的 所以 我们还得对返回的string做一下去零处理

/**
 * 根据输入的字符串返回按照规则去零后的字符串,格式如:一千零一
 *  @param {string} str 中文数字 如 一千零零一
 */
export clearZero(str){
    const regMiddle = /零{2}/g
    const regEnd = /零?零$/
    str = str.replace(regMiddle, '零')
    return str.replace(regEnd, '')
}
复制代码
  1. 通过clearZero函数首先将匹配中间有两个零相连的情况,转为一个零
  2. 然后判断结尾是否有一个至两个零的情况,将它们清空
  3. 注意点: replace 不会改变原来的值,需要将操作后的结果重新赋值

将 numberToChinese 函数改为如下

export numberToChinese(number) {
      number = String(parseInt(number))
      const ChineseText = '零一二三四五六七八九'
      const smallUnit = '十百千'
      const length = number.length
      let n = length - 2
      let string = ''
      for (var i = 0; i < length; i++) {
        let num = number.charAt(i)
        string += ChineseText.charAt(num)
        string += num > 0 ? smallUnit.charAt(n) : ''
        n--
      }
      return  clearZero(string)
    }
复制代码

总结

  1. 四位数以下的数字转换成中文的方法已经完成了 ,更多位数的转换原理相同,有个方法就是将多位数的数字截取成 四位为一组,分组处理,最后将结果拼接起来,这样可能会减少一些逻辑判断。
  2. 核心部分就是通过 charAt 取数字字符串,然后通过数组去找定义好的ChineseText对应的中文,定义了一个 n 来取当前位数对应的单位

以上所述就是小编给大家介绍的《记一次bug解决过程(数字转化成中文)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

利用Python进行数据分析

利用Python进行数据分析

Wes McKinney / 唐学韬 / 机械工业出版社 / 2013-11-18 / 89.00

【名人推荐】 “科学计算和数据分析社区已经等待这本书很多年了:大量具体的实践建议,以及大量综合应用方法。本书在未来几年里肯定会成为Python领域中技术计算的权威指南。” ——Fernando Pérez 加州大学伯克利分校 研究科学家, IPython的创始人之一 【内容简介】 还在苦苦寻觅用Python控制、处理、整理、分析结构化数据的完整课程?本书含有大量的实践案例,......一起来看看 《利用Python进行数据分析》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试