Ruby字符串解压代码中字符乘非数字值为何未触发循环报错
问题背景
存在一个接收字符串作为入参的解压方法,入参遵循固定格式:每个字母后紧跟一个数字。方法逻辑为返回字符串的解压结果:每个字母按照其后方紧邻的数字重复对应次数。
给出的方法实现代码如下:
def uncompress(str) new_str = "" (0 ... str.length - 1).each do |i| new_str += str[i] * str[i + 1].to_i end new_str end
运行结果示例:
uncompress('a2b4c1') # 返回 'aabbbbc'
待解答疑问:
遍历过程中,当
str[i+1]不是数字(即str[i]为数字字符、str[i+1]为字母字符)时,为什么每轮循环中执行str[i] * str[i + 1]的逻辑都没有返回错误?
原因说明
没报错的核心是Ruby的两个默认语法规则,代码刚好踩中规则没有触发异常:
- 代码里不是直接做字符串和字符串的乘法,每次乘之前都对
str[i+1]调用了to_i做类型转换。Ruby中对非数字开头的字符串调用to_i不会抛类型错误,会直接返回整数0,所有纯字母字符调用to_i的结果都是0。 - Ruby原生支持字符串与整数做乘法运算,规则是将原字符串重复整数次后返回新字符串;当乘数为0时,运算结果是空字符串,不会触发异常。
对应到你说的场景:当i遍历到数字字符位置时,i+1刚好是下一个字母,此时执行的逻辑是数字字符 * 字母.to_i,也就是数字字符 * 0,得到空字符串。把空字符串拼接到最终结果里不会产生任何可见效果,也不会中断程序运行,所以全程不会抛错。
可以在Ruby控制台单独验证这两个逻辑:
# 字母转整数 'a'.to_i # => 0 # 字符串乘0 '2' * 0 # => ""
要注意的是,这个写法虽然能跑通正确结果,但属于取巧利用隐式转换的实现:遍历过程中有近一半的循环是无效的(所有i指向数字字符的轮次,都只会生成空字符串),执行效率不高。更合理的实现是设置步长为2遍历,每次只取字母位和它后面紧跟的数字位处理即可。
内容的提问来源于stack exchange,提问作者Daria
相关产品推荐
相关产品推荐

