Код Ruby для проверки Integer [duplicate]

Я создатель клонирования lib, тот, который представил Брэд. Это решение для клонирования объектов без необходимости писать дополнительный код (нет необходимости в сериализуемых объектах или методе impl clone ())

Это довольно быстро, как сказал Брэд, и недавно я загрузил версию, которая даже Быстрее. Обратите внимание, что ручное внедрение метода clone () будет быстрее, чем clone lib, но опять же вам нужно будет написать много кода.

Cloner lib работал для меня хорошо, так как я его использую в реализации кэша для сайта с очень интенсивным трафиком (~ 1 млн запросов / день). Кэш должен клонировать приблизительно 10 объектов на запрос. Он достаточно надежный и стабильный. Но, пожалуйста, имейте в виду, что клонирование не без риска. Lib может быть настроен для печати каждого экземпляра класса, который он клонирует во время dev. Таким образом, вы можете проверить, клонирует ли он то, что, по вашему мнению, нужно клонировать, - графы объектов могут быть очень глубокими и содержать ссылки на удивительно большое количество объектов. С помощью clone lib вы можете поручить ему не клонировать объекты, которые вам не нужны, т. Е. Синглтоны.

112
задан Tony 5 August 2009 в 22:28
поделиться

19 ответов

Вы можете использовать регулярные выражения. Вот функция с предложениями @ 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  
120
ответ дан sscirrus 27 August 2018 в 18:45
поделиться
  • 1
    Неплохо. В Ruby вы обычно опускаете & quot; return & quot; если возвращаемое значение генерируется в последнем выражении в функции. Это также вернет целочисленное значение нуля, вы, вероятно, хотите иметь логическое значение, поэтому что-то вроде !! (str = ~ / ^ [- +]? [0-9] + $ /). Затем вы можете добавить его в String и оставить аргумент, используя & quot; self & quot; вместо "str", а затем вы можете изменить имя на "is_i? & quot; ... – janm 5 August 2009 в 23:16
  • 2
    Благодаря! У меня нет абсолютно никакой информации о рубиновых конвенциях и практиках. Я просто сделал быстрый google на рубине и регулярных выражениях, чтобы увидеть синтаксис, изменил регулярное выражение, чтобы применить к проблеме, и протестировал ее. Это довольно аккуратно. Возможно, мне придется больше смотреть на него, когда у меня будет больше свободного времени. – Rado 5 August 2009 в 23:21
  • 3
    У вас есть правильная идея, но она не соответствует бинарным или шестнадцатеричным литералам (см. Мое отредактированное решение ниже). – Sarah Mei 6 August 2009 в 04:56
  • 4
    Сара, это не ошибка, это особенность! – janm 6 August 2009 в 08:51
  • 5
    Два комментария. Вы можете использовать /regexp/ === self вместо конструкции !!(self =~ /regexp/). Вы можете использовать класс символов '\ d' вместо [0-9] – wich 24 September 2012 в 02:24

Расширяясь в ответе @ rado выше, вы также можете использовать тройную инструкцию для принудительного возврата истинных или ложных логических значений без использования двойных импульсов. Конечно, версия с двойным логическим отрицанием является более кратким, но, вероятно, труднее читать для новичков (например, я).

class String
  def is_i?
     self =~ /\A[-+]?[0-9]+\z/ ? true : false
  end
end
0
ответ дан adeluccar 27 August 2018 в 18:45
поделиться
class String
  def integer?
    Integer(self)
    return true
  rescue ArgumentError
    return false
  end
end
  1. Не имеет префикса is_. Я нахожу это глупым в вопросительных методах, мне нравится "04".integer? намного лучше, чем "foo".is_integer?.
  2. Он использует разумное решение sepp2k, которое проходит для "01" и т. Д.
  3. Объектно-ориентированный, yay.
8
ответ дан August Lilleaas 27 August 2018 в 18:45
поделиться
  • 1
    +1 для его именования #integer ?, -1 для загромождения String с ним: -P – Avdi 5 August 2009 в 22:45
  • 2
    Куда еще это пойдет? integer?("a string") ftl. – August Lilleaas 5 August 2009 в 22:47
  • 3
    String#integer? - это общий патч, который каждый рубиновый кодер и их кузен любят добавлять к языку, приводя к кодовым базам с тремя различными тонко несовместимыми реализациями и неожиданным поломкой. Я усвоил это на крупных проектах Ruby. – Avdi 5 August 2009 в 22:51
  • 4
    Те же комментарии, что и выше: исключения не должны использоваться для потока управления. – Sarah Mei 5 August 2009 в 23:08
  • 5
    Даунсайд: это решение тратит одно конвертирование. – Robert Klemme 31 January 2014 в 19:02
  def isint(str)
    return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/)
  end
3
ответ дан Brian Webster 27 August 2018 в 18:45
поделиться

лично мне нравится подход к исключению, хотя я бы сделал его немного терпелив.

class String
  def integer?(str)
    !!Integer(str) rescue false
  end
end

Однако, как уже отмечали другие, это не работает с восьмеричными строками ...

3
ответ дан eightbitraptor 27 August 2018 в 18:45
поделиться

Более простым способом может быть

/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true
3
ответ дан gouravtiwari21 27 August 2018 в 18:45
поделиться
"12".match(/^(\d)+$/)      # true
"1.2".match(/^(\d)+$/)     # false
"dfs2".match(/^(\d)+$/)    # false
"13422".match(/^(\d)+$/)   # true
18
ответ дан Maciej Krasowski 27 August 2018 в 18:45
поделиться
  • 1
    Он не возвращает экземпляры true и false, но MatchData и nil – Stefan 17 September 2013 в 14:19
  • 2
    Это не то, что оно возвращает, но если оно совпадает – Maciej Krasowski 8 August 2014 в 10:40
  • 3
    Оберните его с помощью !! или используйте 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 не будет действительным целым литералом.

60
ответ дан Milos 27 August 2018 в 18:45
поделиться
  • 1
    Чувак ... провоцирует исключение только для преобразования числа? Исключения не являются потоком управления. – Sarah Mei 5 August 2009 в 23:05
  • 2
    Это не так, но, к сожалению, это канонический способ определения «целочисленности». строки в Ruby. Методы, использующие #to_i, слишком нарушены из-за его вседозволенности. – Avdi 5 August 2009 в 23:17
  • 3
    Для тех, кто задается вопросом, почему Integer («09») недействителен, поскольку «0» делает его восьмеричным, а 9 - недействительным восьмеричным числом. osdir.com/ml/lang.ruby.general/2002-08/msg00247.html – Andrew Grimm 6 August 2009 в 00:25
  • 4
    Сара: вы можете использовать Regex, но для обработки всех случаев, которые Ruby делает при синтаксическом анализе целых чисел (отрицательные числа, шестнадцатеричные, восьмеричные, подчеркивания, например, 1_000_000), это будет очень большое Regex и легко ошибиться. Integer() является каноническим, потому что с Integer () вы точно знаете, что все, что Ruby считает целочисленным литералом, будет принято, а все остальное будет отклонено. Дублирование того, что уже дал вам язык, - это, пожалуй, худший запах кода, чем использование исключений для контроля. – Avdi 6 August 2009 в 15:32
  • 5
    @Rado Так изобретает колесо. – sepp2k 20 May 2014 в 21:13

Я не уверен, что это было вокруг, когда задавался этот вопрос, но ... Для любого, кто наткнулся на этот пост, самым простым способом является

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

.is_a? будет работать с любым объектом!

-2
ответ дан Newbie 27 August 2018 в 18:45
поделиться
  • 1
    Это не то, что задает первоначальный вопрос. OP хочет знать, является ли строка целым числом. например "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
-1
ответ дан Richard Erickson 27 August 2018 в 18:45
поделиться

Вы можете сделать один лайнер:

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
19
ответ дан Robert Klemme 27 August 2018 в 18:45
поделиться
  • 1
    Что касается темы «исключение как поток управления»: поскольку мы не знаем, как использовать метод, мы не можем действительно судить о том, подходят ли исключения или нет. Если строка вводится и требуется целое число, то предоставление не целого числа гарантирует исключение. Хотя тогда, возможно, обработка не в том же методе, и мы, вероятно, просто сделаем Integer (str) .times {| i | ставит i} или что угодно. – Robert Klemme 6 August 2009 в 08:07

Решение:

# /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.
2
ответ дан Sachin 27 August 2018 в 18:45
поделиться
  • 1
    Не могли бы вы добавить небольшое объяснение этому, пожалуйста? – stef 24 May 2017 в 08:08
  • 2
    @stef - Я сделал то же самое. Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы. – Sachin 25 May 2017 в 09:57

Ну, вот простой способ:

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
139
ответ дан Sarah Mei 27 August 2018 в 18:45
поделиться
  • 1
    "01" .to_i.to_s! = "01" – sepp2k 5 August 2009 в 22:37
  • 2
    Не могли бы вы заменить self.to_i.to_s == self на Integer self rescue false? – Meredith L. Patterson 5 August 2009 в 22:38
  • 3
    Вы могли бы, но это было бы плохой формой. Вы не используете исключения в качестве потока управления, и ни один код не должен содержать «rescue false». (или «спасение истинно»). Некоторые простые gsub'ing заставили бы мое решение работать для случаев кросс, не указанных OP. – Sarah Mei 5 August 2009 в 23:06
  • 4
    Я знаю, что многие используют его, и это, безусловно, эстетично. Для меня, хотя это показатель того, что код нуждается в реструктуризации. Если вы ожидаете исключения ... это не исключение. – Sarah Mei 6 August 2009 в 04:59
  • 5
    Я согласен с тем, что исключения не должны использоваться в качестве потока управления. Я не думаю, что требование состоит в том, чтобы распознанные числа, ориентированные на разработчиков. В ситуациях, отличных от программистов, которые можно рассматривать как ошибку, особенно учитывая ту возможную путаницу вокруг ведущих нулей и восьмеричных. Также не согласуется с to_i. Ваш код не обрабатывает & quot; -0123 & quot; дело. Как только вы справитесь с этим случаем, вам не нужно отдельное регулярное выражение для восьмеричного. Вы можете просто продолжить, используя «any?». Единственным утверждением в вашей функции может быть & quot; [/ re1 /, / re2 /, / re3 /] .any? {| re | self = ~ re} & quot ;, без предложений if или return. – janm 6 August 2009 в 08:49

Наилучший и простой способ использует 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

4
ответ дан shiva 27 August 2018 в 18:45
поделиться
  • 1
    @downvoter вы можете объяснить? – shiva 19 November 2014 в 04:44
  • 2
    Я рад, что заметил ваш ответ. В противном случае я бы пошел с "Integer" когда мне понадобился «Float». – Jeff Zivkovic 30 May 2018 в 03:21
  • 3
    Это простой, но лучший ответ! В большинстве случаев нам не нужен модный патч для класса String. Это лучше для меня! – Anh Nguyen 28 June 2018 в 06:50

Я предпочитаю:

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?
5
ответ дан skozz 27 August 2018 в 18:45
поделиться

Хотя следует избегать явного использования оператора равенства случая, 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
1
ответ дан Stefan 27 August 2018 в 18:45
поделиться

Для более обобщенных случаев (включая числа с десятичной точкой) вы можете попробовать следующий метод:

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

Подробное объяснение используемого здесь регулярного выражения, посмотрите эту статью в блоге :)

1
ответ дан Taiga 27 August 2018 в 18:45
поделиться
  • 1
    Нет необходимости вызывать 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.

2
ответ дан three 27 August 2018 в 18:45
поделиться
  • 1
    Работает, но это не рекомендуется, поскольку "12blah".to_i => 12. Это может вызвать некоторые проблемы в странных сценариях. – rfsbraz 17 June 2015 в 11:24

вы можете использовать is_a? метод. например. 1.is_a? Integer вернет true

-3
ответ дан Vedprakash Singh 27 August 2018 в 18:45
поделиться
  • 1
    Прочитайте вопрос, который OP хотел проверить, что для строк, а "1".is_a?(Integer) возвращает false – Cyril Duchon-Doris 25 February 2017 в 21:29
Другие вопросы по тегам:

Похожие вопросы: