目前我有这个(糟糕的)代码:
def is_num(num_given)
begin
num_given.to_i
worked = true
rescue
worked = false
ensure
return worked
end
end
我对此进行了重构:
def is_num(num_given)
num_given.to_i.is_a?(Numeric) rescue false
end
这对我来说仍然感觉不对,有更好的方法吗?
这两个实现都适合我的目的,我只是寻找一些代码的兴奋。
答案 0 :(得分:2)
something.is_a?(Numeric)
是要走的路。请参阅后一个示例,无需在输入上调用to_i
。
请注意,如果您正在查看字符串是否为数字,则something.is_a?(Numeric)
将无效...
答案 1 :(得分:2)
这是另一种解决方案。它不像Ruby那样,但这是故意的(例如,while
在这种情况下比str.chars.each
更快。)
# is a character between 0 and 9? (based on C's isdigit())
def digit?(c)
o = c.ord
o >= 48 && o <= 57 # '0'.ord, '9'.ord
end
# is a string numeric (i.e., represented as an integer or decimal)?
def numeric?(str)
str = str.to_s unless str.is_a?(String)
l = str.length
i = 0
while i < l
c = str[i]
if c == '.' || c == '-'
i += 1
next
end
return false if !digit?(c)
i += 1
end
true
end
以下是单元测试。如果我错过了一个案子,请告诉我。对于其他回答者,只需将subject
块更改为您的功能。
if $0 == __FILE__
require 'minitest/autorun'
describe :digit? do
%w(- + : ? ! / \ ! @ $ ^ & *).each do |c|
it "flunks #{c}" do
digit?(c).must_equal false
end
end
%w(0 1 2 3 4 5 6 7 8 9).each do |c|
it "passes #{c}" do
digit?(c).must_equal true
end
end
end
describe :numeric? do
subject { :numeric? }
%w(0 1 9 10 18 123.4567 -1234).each do |str|
it "passes #{str}" do
method(subject).call(str).must_equal true
end
end
%w(-asdf 123.zzz blah).each do |str|
it "flunks #{str}" do
method(subject).call(str).must_equal false
end
end
[-1.03, 123, 200_000].each do |num|
it "passes #{num}" do
method(subject).call(num).must_equal true
end
end
end
end
答案 2 :(得分:1)
您列出的功能不起作用:
is_num("a") #=> true
问题是它们不会因无效输入而引发错误。你想要的是Integer
,这将引发一个你可以解决的错误:
def is_num(num_given)
!!Integer(num_given) rescue false
end
这有效:
irb(main):025:0> is_num("a")
=> false
irb(main):026:0> is_num(5)
=> true
irb(main):027:0> is_num((1..2))
=> false
irb(main):028:0> is_num("3")
=> true
(尽管如此,可能有一种更自然的方式。)
答案 3 :(得分:0)
您始终可以使用简单的正则表达式:
def is_num(num_given)
num_given =~ /\d+(\.\d+)?/
end