ตรวจสอบว่าตัวแปรเป็นจำนวนเต็มหรือไม่


137

Rails 3 หรือ Ruby มีวิธีการตรวจสอบว่าตัวแปรเป็นจำนวนเต็มหรือไม่?

ตัวอย่างเช่น,

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

ความเป็นไปได้ที่ซ้ำกันของruby 1.9.2 มี is_a หรือไม่? ฟังก์ชั่น?
Andrew Grimm

1
แทนที่จะสนใจว่าตัวแปรนั้นเป็นจำนวนเต็มหรือไม่คุณควรตรวจสอบเพื่อดูว่าตัวแปรตอบสนองto_iหรือไม่ นั่นเป็นส่วนหนึ่งของ "การพิมพ์เป็ด" ของรูบี้: ถ้ามันสามารถทำตัวเหมือนจำนวนเต็มได้
ชายดีบุก

4
@The Tin Man: ไม่ทั้งหมด "hello" .to_i ส่งคืนค่า 0 ซึ่งอาจไม่ใช่สิ่งที่คุณคาดหวัง
EinLama

1
@AnApprentice สำหรับข้อมูลของคุณเป็นนามแฝงที่จะkind_of? is_a?
Jacob Relkin

3
@JacobRelkin is_a?แตกต่างกันเล็กน้อย มันถามว่าวัตถุของอินสแตนซ์ของคลาสเฉพาะ kind_of?ถามว่ามันเป็นอินสแตนซ์หรือลูกของคลาสเฉพาะ fido.is_a? Dogเป็นความจริง; fido.kind_of? Animalเป็นจริงเช่น
Tom Harrison

คำตอบ:


274

คุณสามารถใช้is_a?วิธีการ

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

2
นั่นเจ๋งมาก ทำงานเพื่อตรวจสอบที่อยู่อีเมลให้หรือไม่
AnApprentice

65
@AnApprentice ตั้งแต่เมื่อตรวจสอบที่อยู่อีเมลเป็นส่วนหนึ่งของคำถาม?
Jacob Relkin

4
สิ่งนี้จะไม่ทำงานหากตัวเลขมาในสตริงเช่น "11111111"
Ricbermo

ดูด้านล่างInteger(obj) rescue false นี้จะไม่ทำงานสำหรับ "1" ถ้าคุณต้องการตรวจสอบว่ามันจะแปลง
mc

4
@Ricbermo "1111111" เป็นสตริง สตริงที่เกิดขึ้นและสามารถแปลงเป็นจำนวนเต็มได้
Sqeaky

50

หากคุณต้องการทราบว่าวัตถุนั้นเป็นวัตถุInteger หรือสิ่งที่สามารถแปลงเป็นจำนวนเต็ม (ไม่รวมถึงสิ่งต่าง ๆ เช่น"hello"ซึ่งto_iจะแปลงเป็น0)

result = Integer(obj) rescue false

2
บางทีฉันอาจเป็นแค่ noob แต่การบิดนี้จะช่วยฉันได้ result = Integer (obj) rescue false
John Curry

@ JohnCurry อย่าลังเลที่จะแก้ไขคำตอบหากคุณสามารถปรับปรุงได้ นั่นคือวิธีการทำงานของ SO
Alex D

2
ฉันทำมันถูกปฏิเสธ "การแก้ไขนี้เบี่ยงเบนไปจากความตั้งใจดั้งเดิมของการโพสต์" แต่ไม่ว่าอย่างไรขอบคุณสำหรับคำตอบของคุณมันช่วยฉันแก้ปัญหาของฉันได้!
John Curry

7
จำนวนเต็ม ('08 ') จะล้มเหลวเนื่องจากสตริงที่ถูกตีความว่าเป็นเลขฐานแปดทำให้จำนวนเต็ม ('08', 10) ทำงานได้ดี ในกรณีที่
Jong Bor Lee

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*อาจแก้ไขได้ แต่ฉันต้องการเรียกใช้ผ่านชุดการทดสอบเพื่อให้แน่ใจ สิ่งนี้ยังไม่ตรงกับเครื่องหมายฐานสิบหกหรือสัญลักษณ์ชี้แจง แต่ฉันแน่ใจว่ามันใช้ได้สำหรับบางกรณี
Jeff

1
ทำไมไม่เพียงใช้ regexp นี้\A\d+\z?
NARKOZ

1
เปรียบเทียบกับInteger(obj) rescue falseรหัสจาก @ alex-d ด้านล่าง; regexp อ่านยากและไม่ชัดเจนในความตั้งใจ ทั้งสองงานฉันมาที่คำถามนี้ในความพยายามที่จะแก้ไข regexp ที่สร้างมาไม่ดีซึ่งไม่ได้ทำงานเสมอ :-)
Tom Harrison

17

หากคุณไม่แน่ใจเกี่ยวกับประเภทของตัวแปร (อาจเป็นสตริงของตัวเลข) บอกว่ามันเป็นหมายเลขบัตรเครดิตที่ส่งเข้าไปใน params ดังนั้นในตอนแรกมันจะเป็นสตริง แต่คุณต้องการตรวจสอบให้แน่ใจว่ามันไม่ได้ ' ไม่มีตัวอักษรใด ๆ ในนั้นฉันจะใช้วิธีนี้:

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

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

@Benny ชี้ให้เห็นถึงการกำกับดูแลของวิธีการนี้โปรดจำไว้ว่า:

is_number? "01" # false. oops!

ขอบคุณคุณประหยัดวันของฉัน สำหรับใครที่ต้องตรวจสอบว่ามันลอยหรือไม่สามารถเปลี่ยนได้โดยตรงobj.to_s == obj.to_f.to_sเช่นเดียวกับในกรณีของฉัน
ksugiarto

เอ๊ดมันด์ที่ฉลาด! 🙌
siwalikm

ยอดเยี่ยมฉันชอบสิ่งนี้มากกว่า Integer ('123fh') และข้อยกเว้นการช่วยเหลือ
zw963


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ค่าจำนวนเต็มไม่ได้เป็นเท็จมันเป็นความจริง ( !!0 #=> true) (ขอบคุณ @prettycoder)

แก้ไข

อาเพิ่งค้นพบเกี่ยวกับคดีความมืด ... ดูเหมือนว่าจะเกิดขึ้นก็ต่อเมื่อตัวเลขอยู่ในอันดับที่หนึ่ง

"12blah".to_i => 12

0 มีความจริงในทับทิม!
prettycoder

1
@prettycoder ขอบคุณสำหรับหัวขึ้นฉันจะแก้ไขปัญหานี้ทันทีในคำตอบ
Cyril Duchon-Doris

1

หากต้องการใช้ประโยชน์จากคำตอบของ Alex Dโดยใช้การปรับแต่ง :

module CoreExtensions
  module Integerable
    refine String do
      def integer?
        Integer(self)
      rescue ArgumentError
        false
      else
        true
      end
    end
  end
end

ต่อมาในชั้นเรียนของคุณ:

require 'core_ext/string/integerable'

class MyClass
  using CoreExtensions::Integerable

  def method
    'my_string'.integer?
  end
end

0

ฉันมีปัญหาที่คล้ายกันก่อนที่จะพยายามที่จะตรวจสอบว่าสิ่งที่เป็นสตริงหรือจำนวนใด ๆ ฉันได้ลองใช้นิพจน์ทั่วไป แต่นั่นไม่น่าเชื่อถือสำหรับกรณีการใช้งานของฉัน แต่คุณสามารถตรวจสอบคลาสของตัวแปรเพื่อดูว่ามันเป็นสืบทอดของคลาสที่เป็นตัวเลขหรือไม่

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 String num = Float (NUM) ช่วยเหลือปลายปลอม

new_num = จำนวนเต็มช่วยเหลือ (จำนวน) false false

ทำให้ NUM

ใส่ new_num

ทำให้ num == new_num

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.