注册
web

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

说在前面



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



功能背景


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



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


问题描述


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



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


方法实现


1、个位级映射表


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

2、单位映射表


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)

if (hasZero && current > 0) {
current *= 10;
hasZero = false;
}
current += numMap[char];


  • 遇到单位

    • 如果是十/百/千:把存着的数字乘上倍数
      (如「三百」→3×100=300)

    current = current === 0 ? unit.value : current * unit.value;
    section += current;
    current = 0;


    • 遇到万/亿:先结算当前数字,将当前数字加到总数上

    processSection();
    section = (section + current) * unit.value;
    total += section;
    section = 0;


  • 遇到零:做个标记,提醒下个数字要占位
    (如「三百零五」→300 + 0 +5=305)

if (char === "零") {
hasZero = true;
continue;
}

4、完整代码


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



作者:JYeontu
来源:juejin.cn/post/7485936146071765030

0 个评论

要回复文章请先登录注册