从字符串里提取有效数,大于2^31 − 1 返回 2^31 − 1,小于−2^31,返回−2 ^ 31。
输入: "42"
输出: 42
输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
输入: " +42"
输出: 42
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
因此无法执行有效的转换。
最初的解法
var myAtoi = function(str) {
let result = +(str.trim().match(/^[-+]?\d+/g) || [])[0];
if(result){
if(result > 2**31 - 1){
return 2**31 - 1;
}
else if(result < -(2**31)){
return -(2**31);
}
return result;
}
return 0;
};
match
函数可能返回null
+null
会返回 0
-(2**31) 的()不加会报一个晦涩的语法错误,大概是造成了代码执行的二意性。
Uncaught SyntaxError: Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence
上面的问题在于用了太多的判断,其实parseInt函数可以很好的起到过滤作用,但我认为用正则起到很好的锻炼作用
参考后的解法
var myAtoi = function(str) {
let number = +parseInt(str);
let result = number
? Math.max(Math.min(number, 2 ** 31 - 1), -(2 ** 31))
: 0;
return result;
};
parseInt
可能返回 NaN
,而Boolean(NaN)
返回false
这也意味着 逻辑进入Math.max(Math.min())
后,result不会时NaN
问题
您会觉得 Math.max(Math.min())
这种写法不易读吗?
有趣的事
最初的解法是有let isNumber = !Number.isNaN(result);
这段代码,我以为+null
会返回 NaN
,Boolean(NaN)
返回false
,然后删掉了这行代码,结果发现+null
会返回 0,写文章的过程中,认知发生了两次变化。
网友评论