我想将zipcodes规范化为5位数字,用零替换任何丢失的字符,如下所示:
"95616" >> "95616"
"854" >> "00854"
"062" >> "00062"
"0016" >> "00016"
我尝试使用像sprintf("%05s", zipcode)
这样的sprintf,就像这样
sprintf("%0.5d", zipcode)
。两者都给出错误答案。使用s
:
"95616" >> "95616"
"854" >> " 854"
"062" >> " 062"
"0016" >> " 0016"
这是正确的字符数,但使用空格而不是零。
使用d
:
"95616" >> "95616"
"854" >> "00854"
"062" >> "00050"
"0016" >> "00014"
在这种情况下,sprintf()的正确用法是什么?
答案 0 :(得分:25)
不要用sprintf
折磨自己:
puts "123".rjust(5, '0') # => 00123
答案 1 :(得分:8)
你对sprintf的使用很好。你的问题是062(和0016)是八进制(任何以0开头的整数),转换为base10时变为50。
解决方案是在它击中你的Ruby应用程序之前摆脱它。假设它是一个字符串(因为你的例子显示了字符串),你可以这样做:
"062".gsub /^0/, ''
然后继续填充和打印格式。
另一种方法是明知将它打印为八进制,如果你知道它以0开头:
"%05o" % 062 # => "00062"
当然,如果您可以控制输入,那么最好的办法是确保人们不会通过输入您不期望的数字来破坏您的代码。例如
"%05s" % 0xff0055 # => 16711765
"%05x" % 0xff0055 # => "ff0055"
检查输入会将问题从格式化问题更改为验证问题,最好是防止而不是处理。
(古怪的%语法是printf
/ sprintf
)
答案 2 :(得分:6)
你想要%05d。 String#%也是一个捷径:
"%05d" % "123" #=> 00123
答案 3 :(得分:2)
whirlwin的解决方案在我看来是一个有效的(通用填充)解决方案。只需用max:
进行改进zipcode.insert 0, '0' * ([5 - zipcode.length, 0].max)
检查一下:
az = ["95616", "854", "062", "0016", '1', '123456']
az.collect {|zipcode| zipcode.insert 0, '0' * (5 - zipcode.length) }
$ ruby -w t.rb
t.rb:2:in `*': negative argument (ArgumentError)
添加最大值以应对负值:
az = ["95616", "854", "062", "0016", '1', '123456']
az.collect {|zipcode| zipcode.insert 0, '0' * ([5 - zipcode.length, 0].max) }
p az
$ ruby -w t.rb
["95616", "00854", "00062", "00016", "00001", "123456"]
答案 4 :(得分:0)
虽然这种方法确实没有使用sprintf
,但它应该在一行代码中解决您的问题:
zipcode.insert 0, '0' * (5 - zipcode.length)
答案 5 :(得分:0)
感谢大家的投入。我希望了解更多关于sprintf的信息,特别是在解决方案中使用sprintf,所有的想法都非常有用。我最终想出了一个针对我的问题的一个hacky解决方案,似乎是灵活的,还没有被提及,所以我想我会发布它。
正如我所提到的,如果数字字符串不够长,sprintf("%05s", zipcode)
将返回空格而不是零,但它确实返回了正确的空格数 - 所以我只是将gsub
链接到结束用零替换空格。
sprintf("%05s", zipcode).gsub!(" ", "0")
如果此解决方案存在任何重大问题,请与我们联系。我测试了它,到目前为止似乎有效。