Перевірка, чи є змінною ціле число


137

Чи має Rails 3 або Ruby вбудований спосіб перевірити, чи є змінною ціле число?

Наприклад,

1.is_an_int #=> true
"dadadad@asdasd.net".is_an_int #=> false?


1
Замість того, щоб дбати про те, чи є змінна цілим числом, слід перевірити, чи відповідає змінна to_i. Це частина "качки" Рубі: Якщо вона може діяти як ціле число, поводьтеся з нею.
Олов'яний чоловік

4
@ The Tin Man: Не зовсім. "привіт" .to_i повертає 0, що може бути не таким, як ви очікуєте.
EinLama

1
@AnApprentice Для вашої інформації kind_of?це псевдонім до is_a?.
Яків Релькін

3
@JacobRelkin is_a?дещо інший; він запитує, чи є об'єктом екземпляра певного класу; kind_of?запитує, чи це екземпляр чи дитина конкретного класу. fido.is_a? Dogправда; fido.kind_of? Animalвірно, наприклад.
Том Харрісон

Відповіді:


274

Можна використовувати is_a?метод

>> 1.is_a? Integer
=> true
>> "dadadad@asdasd.net".is_a? Integer
=> false
>> nil.is_a? Integer
=> false

2
Це дуже круто. це працює для перевірки електронних адрес?
Підручник

65
@AnApprentice З тих пір, коли перевіряли адреси електронної пошти частину питання?
Яків Релькін

4
ця робота не буде, якщо число надходить у рядку типу "11111111"
Річбермо,

дивіться нижче Integer(obj) rescue false Це не буде працювати для "1", якщо ви хочете перевірити, чи буде він перетворений
mc.

4
@Ricbermo "1111111" - це рядок. Рядок, який може бути конвертованим у цілісне число.
Sqeaky

50

Якщо ви хочете знати об'єкт , чи є Integer чи то , що по значенню можуть бути перетворені в Integer (НЕ включаючи такі речі , як "hello", який to_iбуде конвертувати в 0):

result = Integer(obj) rescue false

2
Можливо, я просто ноб, але ця настройка допомогла б мені. результат = Integer (obj) рятування помилково.
Джон Керрі

@JohnCurry, не соромтесь відредагувати відповідь, якщо зможете її покращити. Ось так працює ТАК.
Алекс Д

2
Я це зробив, його відхилили. "Це редагування відхиляється від початкового наміру публікації" Але незалежно, дякую за вашу відповідь, це допомогло мені вирішити мою проблему!
Джон Керрі

7
Integer ('08 ') вийде з ладу через те, що рядок інтерпретується як вісімковий, Integer ('08', 10) працює нормально. Про всяк випадок.
Джонг Бор Лі

1
Не впевнений, чи Integer(2.5) => 2завжди це змістовне перетворення.
mkataja

29

Використовуйте регулярний вираз на рядку:

def is_numeric?(obj) 
   obj.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end

Якщо ви хочете перевірити, чи змінна певного типу, ви можете просто скористатися kind_of?:

1.kind_of? Integer #true
(1.5).kind_of? Float #true
is_numeric? "545"  #true
is_numeric? "2aa"  #false

Це саме те, що я шукав is_numeric?
workdreamer

Я думаю, що це близько, але не зовсім правильно. Наприклад, не вдасться ".34". Проблема, я думаю, що в \d+?тому ?специфицирует нежадібні матч, в той час як вам , ймовірно , хоче додатковий матч. Зміна \d+?до \d*може виправити це, але я хочу , щоб запустити його через набір тестів , щоб переконатися. Це також не відповідає шістнадцятковим або експоненціальним позначенням, але я впевнений, що це добре для певних випадків використання.
Джефф

1
Чому б не просто скористатися цим regexp \A\d+\z:?
NARKOZ

1
Порівняйте з Integer(obj) rescue falseкодом від @ alex-d нижче; regexp важко читати і не зрозумілий у своєму намірі. Обидва працюють, я прийшов до цього питання, намагаючись виправити погано побудований регулярний вираз, який не завжди працював :-)
Том Гаррісон,

17

Якщо ви не впевнені в типі змінної (це може бути рядок числових символів), скажіть, що це номер кредитної картки, переданий в парами, тож спочатку це буде рядок, але ви хочете переконатися, що він не відповідає ' t не має в ньому жодних літерних символів, я б використовував цей метод:

    def is_number?(obj)
        obj.to_s == obj.to_i.to_s
    end

    is_number? "123fh" # false
    is_number? "12345" # true

@ Бенні вказує на нагляд за цим методом, пам’ятайте про це:

is_number? "01" # false. oops!

дякую, ти врятуєш мій день. Для кожного, кому потрібно перевірити, чи він плаває чи ні, він може змінитися безпосередньо obj.to_s == obj.to_f.to_sтак, як у моєму випадку.
ksugiarto

Едмунд, це розумно! 🙌
siwalikm

Дивовижно, я вважаю за краще це, ніж Integer ('123fh') та виняток для порятунку.
zw963

6

Можна використовувати потрійну рівну.

if Integer === 21 
    puts "21 is Integer"
end

5

Там var.is_a? Class(у вашому випадку var.is_a? Integer:); що може відповідати законопроекту. Або там Integer(var), де він кине виняток, якщо він не зможе його розібрати.


3

Більш "способом набору качки" є використання respond_to?таким чином "цілочисельних" або "строкоподібних" класів також можна використовувати

if(s.respond_to?(:match) && s.match(".com")){
  puts "It's a .com"
else
  puts "It's not"
end

2

У разі , якщо вам не потрібно перетворити нульові значення, я вважаю , методи to_iі to_fбути надзвичайно корисним , оскільки вони перетворять рядок або нульове значення (якщо не конвертований або нуль) або фактичне Integerабо Floatзначення.

"0014.56".to_i # => 14
"0014.56".to_f # => 14.56
"0.0".to_f # => 0.0
"not_an_int".to_f # 0
"not_a_float".to_f # 0.0

"0014.56".to_f ? "I'm a float" : "I'm not a float or the 0.0 float" 
# => I'm a float
"not a float" ? "I'm a float" : "I'm not a float or the 0.0 float" 
# => "I'm not a float or the 0.0 float"

EDIT2: будьте обережні, 0ціле значення не є фальсию, це truthy ( !!0 #=> true) (спасибі @prettycoder)

EDIT

Ну щойно дізналися про темні випадки ... Здається, це відбувається лише в тому випадку, якщо число знаходиться на першій позиції

"12blah".to_i => 12

0 - триє в рубінах!
prettycoder

1
@prettycoder спасибі за підняту голову, я це негайно
Кирило Дюшон-Доріс


0

У мене виникли подібні проблеми, перш ніж намагатися визначити, чи є щось рядком чи будь-яким чисельним числом. Я намагався використовувати регулярний вираз, але це не є надійним для мого використання. Натомість ви можете перевірити клас змінної, щоб побачити, чи є вона нащадком класу Numeric.

if column.class < Numeric
  number_to_currency(column)
else
  column.html_safe
end

У цій ситуації ви також можете замінити будь-якого з числових нащадків: BigDecimal, Date :: Infinity, Integer, Fixnum, Float, Bignum, Rational, Complex


-1

Можливо, ви шукаєте щось подібне:

Прийняти "2.0 або 2.0 як INT, але відхилити 2.1 та" 2.1 "

num = 2,0

якщо num.is_a? Рядок num = Float (num) рятувальний помилковий кінець

new_num = Integer (num) рятування помилково

ставить num

ставить new_num

ставить num == new_num

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.