怎么将中文数字转为阿拉伯数字?

说在前面

最近实现了一个b站插件,可以通过语音来控制播放页面上指定的视频,在语音识别的过程中遇到了需要将中文数字转为阿拉伯数字的情况,在这里分享一下具体事例和处理过程。

功能背景

先介绍一下功能背景,页面渲染的时候会先对视频进行编号处理,具体如下:

比如我们想要播放第4个视频的话,我们只需要说"第4个",插件就能帮我们选择第四个视频进行播放。

问题描述

功能背景我们已经了解了,那么问题是出在哪里呢?

如上图,这里识别出来的语音文本数字是中文数字,这样跟页面的视频编号无法对应上,因此我们需要实现一个方法来将中文转为阿拉伯数字。

方法实现

1、个位级映射表

javascript 复制代码
const numMap = {
  零: 0,一: 1,壹: 1,二: 2,两: 2,
  三: 3,叁: 3,四: 4,肆: 4,五: 5,
  伍: 5,六: 6,陆: 6,七: 7,柒: 7,
  八: 8,捌: 8,九: 9,玖: 9,
};

2、单位映射表

javascript 复制代码
const unitMap = {
  十: { value: 10, sec: false },
  拾: { value: 10, sec: false },
  百: { value: 100, sec: false },
  佰: { value: 100, sec: false },
  千: { value: 1000, sec: false },
  仟: { value: 1000, sec: false },
  万: { value: 10000, sec: true },
  萬: { value: 10000, sec: true },
  亿: { value: 100000000, sec: true },
  億: { value: 100000000, sec: true }
};

3、处理流程

  • 遇到数字:先存起来(比如「三」记作3)
javascript 复制代码
if (hasZero && current > 0) {
  current *= 10;
  hasZero = false;
}
current += numMap[char];
  • 遇到单位

    • 如果是十/百/千:把存着的数字乘上倍数 (如「三百」→3×100=300)
    javascript 复制代码
    current = current === 0 ? unit.value : current * unit.value;
    section += current;
    current = 0;
    • 遇到万/亿:先结算当前数字,将当前数字加到总数上
    javascript 复制代码
    processSection();
    section = (section + current) * unit.value;
    total += section;
    section = 0;
  • 遇到零:做个标记,提醒下个数字要占位 (如「三百零五」→300 + 0 +5=305)

javascript 复制代码
if (char === "零") {
  hasZero = true;
  continue;
}

4、完整代码

javascript 复制代码
function chineseToArabic(chineseStr) {
  // 映射表(支持简繁)
  const numMap = {
    零: 0,一: 1,壹: 1,二: 2,两: 2,
    三: 3,叁: 3,四: 4,肆: 4,五: 5,
    伍: 5,六: 6,陆: 6,七: 7,柒: 7,
    八: 8,捌: 8,九: 9,玖: 9,
  };
  //单位映射表
  const unitMap = {
    十: { value: 10, sec: false },
    拾: { value: 10, sec: false },
    百: { value: 100, sec: false },
    佰: { value: 100, sec: false },
    千: { value: 1000, sec: false },
    仟: { value: 1000, sec: false },
    万: { value: 10000, sec: true },
    萬: { value: 10000, sec: true },
    亿: { value: 100000000, sec: true },
    億: { value: 100000000, sec: true }
  };

  let total = 0; // 最终结果
  let section = 0; // 当前小节
  let current = 0; // 当前累加值
  let hasZero = false; // 零标记

  const processSection = () => {
    section += current;
    current = 0;
  };

  for (const char of chineseStr) {
    if (numMap.hasOwnProperty(char)) {
      if (char === "零") {
        hasZero = true;
        continue;
      }

      if (hasZero && current > 0) {
        current *= 10;
        hasZero = false;
      }
      current += numMap[char];
    } else if (unitMap.hasOwnProperty(char)) {
      const unit = unitMap[char];

      if (unit.sec) {
        // 处理万/亿分段
        processSection();
        section = (section + current) * unit.value;
        total += section;
        section = 0;
      } else {
        current = current === 0 ? unit.value : current * unit.value;
        section += current;
        current = 0;
      }
      hasZero = false;
    }
  }

  const last2 = chineseStr.slice(-2)[0];
  const last2Unit = unitMap[last2];
  if (last2Unit) {
    current = (current * last2Unit.value) / 10;
  }
  return total + section + current;
}

功能测试

柒億零捌拾萬

十萬三十

十萬三

二百五

二百零五

插件信息

对我上述提到的插件感兴趣的同学可以看下我前面发的这篇文章:

juejin.cn/post/748557...

公众号

关注公众号『 前端也能这么有趣 』,获取更多有趣内容。

发送 加群 还可以加入群聊,一起来学习(摸鱼)吧~

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

相关推荐
前端爆冲几秒前
项目中无用export的检测方案
前端
旧味清欢|11 分钟前
关注分离(Separation of Concerns)在前端开发中的实践演进:从 XMLHttpRequest 到 Fetch API
javascript·http·es6
热爱编程的小曾28 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin39 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox1 小时前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
-代号95271 小时前
【JavaScript】十四、轮播图
javascript·css·css3
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX187302 小时前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js