Если мы рассмотрим общие сценарии, в которых может быть выбрано это исключение, доступ к свойствам с объектом вверху.
Пример:
string postalcode=Customer.Address.PostalCode;
//if customer or address is null , this will through exeption
здесь, если адрес имеет значение null, то вы получите NullReferenceException.
Итак, в качестве практики мы всегда должны использовать проверку нуля, прежде чем обращаться к свойствам в таких объектах (особенно в общих)
string postalcode=Customer?.Address?.PostalCode;
//if customer or address is null , this will return null, without through a exception
Вы можете использовать регулярные выражения. Вот функция с предложениями @ janm.
class String
def is_i?
!!(self =~ /\A[-+]?[0-9]+\z/)
end
end
Отредактированная версия в соответствии с комментарием от @wich:
class String
def is_i?
/\A[-+]?\d+\z/ === self
end
end
Если вам нужно только проверить положительные числа
if !/\A\d+\z/.match(string_to_check)
#Is not a positive number
else
#Is all good ..continue
end
Расширяясь в ответе @ rado выше, вы также можете использовать тройную инструкцию для принудительного возврата истинных или ложных логических значений без использования двойных импульсов. Конечно, версия с двойным логическим отрицанием является более кратким, но, вероятно, труднее читать для новичков (например, я).
class String
def is_i?
self =~ /\A[-+]?[0-9]+\z/ ? true : false
end
end
class String
def integer?
Integer(self)
return true
rescue ArgumentError
return false
end
end
is_
. Я нахожу это глупым в вопросительных методах, мне нравится "04".integer?
намного лучше, чем "foo".is_integer?
. "01"
и т. Д. String#integer?
- это общий патч, который каждый рубиновый кодер и их кузен любят добавлять к языку, приводя к кодовым базам с тремя различными тонко несовместимыми реализациями и неожиданным поломкой. Я усвоил это на крупных проектах Ruby.
– Avdi
5 August 2009 в 22:51
def isint(str)
return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/)
end
Более простым способом может быть
/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true
"12".match(/^(\d)+$/) # true
"1.2".match(/^(\d)+$/) # false
"dfs2".match(/^(\d)+$/) # false
"13422".match(/^(\d)+$/) # true
!!
или используйте present?
, если вам нужны логические !!( "12".match /^(\d)+$/ )
или "12".match(/^(\d)+$/).present?
(последние требуют Rails / activesupport)
– mahemoff
17 September 2015 в 15:33
Вы можете использовать Integer(str)
и посмотреть, возникает ли он:
def is_num?(str)
!!Integer(str)
rescue ArgumentError, TypeError
false
end
Добавление: Следует отметить, что, хотя это возвращает true для "01"
, это не для "09"
, просто потому, что 09
не будет действительным целым литералом.
#to_i
, слишком нарушены из-за его вседозволенности.
– Avdi
5 August 2009 в 23:17
Integer()
является каноническим, потому что с Integer ()
вы точно знаете, что все, что Ruby считает целочисленным литералом, будет принято, а все остальное будет отклонено. Дублирование того, что уже дал вам язык, - это, пожалуй, худший запах кода, чем использование исключений для контроля.
– Avdi
6 August 2009 в 15:32
Я не уверен, что это было вокруг, когда задавался этот вопрос, но ... Для любого, кто наткнулся на этот пост, самым простым способом является
var = "12"
var.is_a?(Integer) # returns false
var.is_a?(String) # returns true
var = 12
var.is_a?(Integer) # returns true
var.is_a?(String) # returns false
"12".is_an_integer? == true
"not12".is_an_integer? == false
12.is_an_integer? == true
– Marklar
25 April 2016 в 11:40
Один вкладыш в string.rb
def is_integer?; true if Integer(self) rescue false end
Вы можете сделать один лайнер:
str = ...
int = Integer(str) rescue nil
if int
int.times {|i| p i}
end
или даже
int = Integer(str) rescue false
В зависимости от того, что вы пытаетесь сделать, вы также можете напрямую использовать начальный конечный блок с условие спасения:
begin
str = ...
i = Integer(str)
i.times do |j|
puts j
end
rescue ArgumentError
puts "Not an int, doing something else"
end
Решение:
# /initializers/string.rb
class String
IntegerRegex = /^(\d)+$/
def integer?
!!self.match(IntegerRegex)
end
end
# any_model_or_controller.rb
'12345'.integer? # true
'asd34'.integer? # false
Объяснение:
/^(\d)+$/
- выражение regex для нахождения цифр в любой строке. Вы можете проверить выражения и результаты регулярных выражений на http://rubular.com/ . IntegerRegex
, чтобы избежать ненужного выделения памяти каждый раз, когда мы ее используем в методе. integer?
- это вопросительный метод, который должен возвращать true
или false
. match
- метод в строке, который соответствует вхождениям в соответствии с данное выражение регулярного выражения в аргументе и возвращает согласованные значения или nil
. !!
преобразует результат метода match
в эквивалентный булев. String
- это исправление обезьяны, которое ничего не меняет в существующих функциях String, но добавляет еще один метод с именем integer?
для любого объекта String. Ну, вот простой способ:
class String
def is_integer?
self.to_i.to_s == self
end
end
>> "12".is_integer?
=> true
>> "blah".is_integer?
=> false
EDIT: Я не согласен с решениями, которые вызывают исключение для преобразования строки. Исключения - это не поток управления, и вы также можете сделайте это правильно. Тем не менее, мое решение выше не касается целых чисел, отличных от base-10. Итак, вот как это сделать, не прибегая к исключениям:
class String
def integer?
[ # In descending order of likeliness:
/^[-+]?[1-9]([0-9]*)?$/, # decimal
/^0[0-7]+$/, # octal
/^0x[0-9A-Fa-f]+$/, # hexadecimal
/^0b[01]+$/ # binary
].each do |match_pattern|
return true if self =~ match_pattern
end
return false
end
end
self.to_i.to_s == self
на Integer self rescue false
?
– Meredith L. Patterson
5 August 2009 в 22:38
Наилучший и простой способ использует Float
val = Float "234" rescue nil
Float "234" rescue nil #=> 234.0
Float "abc" rescue nil #=> nil
Float "234abc" rescue nil #=> nil
Float nil rescue nil #=> nil
Float "" rescue nil #=> nil
Integer
также хорошо, но он вернет 0
для Integer nil
Я предпочитаю:
config / initializers / string.rb
class String
def number?
Integer(self).is_a?(Integer)
rescue ArgumentError, TypeError
false
end
end
, а затем:
[218] pry(main)> "123123123".number?
=> true
[220] pry(main)> "123 123 123".gsub(/ /, '').number?
=> true
[222] pry(main)> "123 123 123".number?
=> false
или проверить номер телефона:
"+34 123 456 789 2".gsub(/ /, '').number?
Хотя следует избегать явного использования оператора равенства случая, Regexp#===
выглядит очень чистым:
def integer?(str)
/\A[+-]?\d+\z/ === str
end
integer? "123" # true
integer? "-123" # true
integer? "+123" # true
integer? "a123" # false
integer? "123b" # false
integer? "1\n2" # false
Для более обобщенных случаев (включая числа с десятичной точкой) вы можете попробовать следующий метод:
def number?(obj)
obj = obj.to_s unless obj.is_a? String
/\A[+-]?\d+(\.[\d]+)?\z/.match(obj)
end
Вы можете протестировать этот метод в сеансе irb:
(irb)
>> number?(7)
=> #<MatchData "7" 1:nil>
>> !!number?(7)
=> true
>> number?(-Math::PI)
=> #<MatchData "-3.141592653589793" 1:".141592653589793">
>> !!number?(-Math::PI)
=> true
>> number?('hello world')
=> nil
>> !!number?('hello world')
=> false
Подробное объяснение используемого здесь регулярного выражения, посмотрите эту статью в блоге :)
obj.is_a? String
, потому что String # to_s вернется, что, по моему мнению, не требует слишком большой обработки по сравнению с вызовом .is_a?
. Таким образом, вы будете делать только один вызов в этой строке вместо одного или двух. Кроме того, вы можете включить непосредственно !!
внутри метода number?
, потому что по соглашению имя метода, которое заканчивается на ?
, должно возвращать логическое значение. С уважением!
– Giovanni Benussi
5 October 2017 в 15:32
Возможно, не подходит для всех случаев, но для некоторых может быть сделано просто
"12".to_i => 12
"blah".to_i => 0
.
Так что если это число, а не 0, оно вернет число. Если он возвращает 0, это либо строка слова, либо 0.
"12blah".to_i => 12
. Это может вызвать некоторые проблемы в странных сценариях.
– rfsbraz
17 June 2015 в 11:24
вы можете использовать is_a? метод. например. 1.is_a? Integer вернет true
"1".is_a?(Integer)
возвращает false
– Cyril Duchon-Doris
25 February 2017 в 21:29
/regexp/ === self
вместо конструкции!!(self =~ /regexp/)
. Вы можете использовать класс символов '\ d' вместо[0-9]
– wich 24 September 2012 в 02:24