Я создатель клонирования lib, тот, который представил Брэд. Это решение для клонирования объектов без необходимости писать дополнительный код (нет необходимости в сериализуемых объектах или методе impl clone ())
Это довольно быстро, как сказал Брэд, и недавно я загрузил версию, которая даже Быстрее. Обратите внимание, что ручное внедрение метода clone () будет быстрее, чем clone lib, но опять же вам нужно будет написать много кода.
Cloner lib работал для меня хорошо, так как я его использую в реализации кэша для сайта с очень интенсивным трафиком (~ 1 млн запросов / день). Кэш должен клонировать приблизительно 10 объектов на запрос. Он достаточно надежный и стабильный. Но, пожалуйста, имейте в виду, что клонирование не без риска. Lib может быть настроен для печати каждого экземпляра класса, который он клонирует во время dev. Таким образом, вы можете проверить, клонирует ли он то, что, по вашему мнению, нужно клонировать, - графы объектов могут быть очень глубокими и содержать ссылки на удивительно большое количество объектов. С помощью clone lib вы можете поручить ему не клонировать объекты, которые вам не нужны, т. Е. Синглтоны.
Вы можете использовать регулярные выражения. Вот функция с предложениями @ 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
лично мне нравится подход к исключению, хотя я бы сделал его немного терпелив.
class String
def integer?(str)
!!Integer(str) rescue false
end
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