在用微信、支付宝扫码支付时,会弹出一个数字键盘(带有小数点)。在输入金额时,会对用户输入的金额进行纠正,比如输入 .1 会自动变为 0.1,输入 03 会变为 3。
那么我们如何实现这样一个功能呢?
需求分析
考虑到数字键盘,用户只能输入 0-9 和小数点。
我们要实现的是一个函数,把用户输入的字符串转化为合法金额的字符串。经过分析有如下情况:
- 空字符串:输入 '',返回 '';
- 以 0 开头的字符串:输入 '03',返回 '3';
- 以 . 开头的字符串:输入 '.',返回 '0.';
- 3 位小数:输入 '0.258',返回 '0.25';
- 两个小数点:输入 '0.98.',返回 '0.98';
- 合法输入:输入 '3.',返回 '3.';
如何实现
根据以上分析,编写一下验证脚本:
function normalizeCurrency(input) {
// 具体功能实现,最终返回字符串
}
// 验证脚本
const cases = [
{ input: '', output: '' },
{ input: '03', output: '3' },
{ input: '.', output: '0.' },
{ input: '0.258', output: '0.25' },
{ input: '0.98.', output: '0.98' },
{ input: '3.', output: '3.' }
];
cases.forEach((c, index) => {
if (normalizeCurrency(c.input) === c.output) {
console.log(`case ${index} pass`);
} else {
throw `case ${index} fail: expect ${c.output} but ${normalizeCurrency(c.input)}`;
}
});
简单的条件判断实现
function normalizeCurrency(input) {
// 为空的情况
if (input === '') {
return '';
}
const pointIndex = input.indexOf('.');
if (pointIndex > -1) {
// 保留两位小数
input = input.slice(0, pointIndex + 3);
// 去掉末尾多余小数点
if (input.lastIndexOf('.') !== pointIndex) {
input = input.slice(-1);
}
// 首位小数点前补 0
if (pointIndex === 0) {
input = '0' + input;
}
} else {
// 去掉多余的 0
input = Number(input) + '';
}
return input;
}
比较容易想到这种方法,针对分析的每种情况都特殊处理,但是看起来有点繁琐,有没有更好的办法呢?
利用 split 方法
function normalizeCurrency(input) {
if (input === '') return '';
const parts = input.split('.');
const integer = Number(parts[0]);
const point = parts[1] !== undefined ? '.' : '';
const decimal = (parts[1] || '').slice(0, 2);
return integer + point + decimal;
}
该方法利用了 split 的一些特性,代码看起来要简洁一些了,还有没有更简洁的实现了?
正则表达式实现
function normalizeCurrency(input) {
if (input === '') return '';
return input.replace(/(\d*)(\.\d{0,2})?.*/, (match, p1, p2) => {
return Number(p1) + (p2 || '');
});
}
通过正则表达式,代码变得最为简洁,也更容易理解一些。