ฉันต้องการฟังก์ชั่นis_an_integer
ที่ไหน
"12".is_an_integer?
ผลตอบแทนจริง"blah".is_an_integer?
ผลตอบแทนที่เป็นเท็จ
ฉันจะทำสิ่งนี้ในรูบีได้อย่างไร ฉันจะเขียน regex แต่ฉันสมมติว่ามีผู้ช่วยสำหรับสิ่งนี้ที่ฉันไม่ทราบ
ฉันต้องการฟังก์ชั่นis_an_integer
ที่ไหน
"12".is_an_integer?
ผลตอบแทนจริง"blah".is_an_integer?
ผลตอบแทนที่เป็นเท็จฉันจะทำสิ่งนี้ในรูบีได้อย่างไร ฉันจะเขียน regex แต่ฉันสมมติว่ามีผู้ช่วยสำหรับสิ่งนี้ที่ฉันไม่ทราบ
คำตอบ:
คุณสามารถใช้นิพจน์ทั่วไป นี่คือฟังก์ชั่นที่มีคำแนะนำของ @ 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
/regexp/ === self
แทน!!(self =~ /regexp/)
โครงสร้าง คุณสามารถใช้คลาสของตัวละคร '\ d' แทน[0-9]
นี่เป็นวิธีที่ง่าย:
class String
def is_integer?
self.to_i.to_s == self
end
end
>> "12".is_integer?
=> true
>> "blah".is_integer?
=> false
ฉันไม่เห็นด้วยกับวิธีแก้ปัญหาที่กระตุ้นให้เกิดข้อยกเว้นในการแปลงสตริง - ข้อยกเว้นไม่ใช่การควบคุมการไหลและคุณอาจทำในสิ่งที่ถูกต้อง ที่กล่าวว่าวิธีการแก้ปัญหาของฉันไม่ได้จัดการกับจำนวนเต็มไม่ใช่ฐาน 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
?
คุณสามารถใช้Integer(str)
และดูว่ามันเพิ่ม:
def is_num?(str)
!!Integer(str)
rescue ArgumentError, TypeError
false
end
มันควรจะชี้ให้เห็นว่าในขณะที่สิ่งนี้กลับเป็นจริงสำหรับ"01"
มันไม่ได้"09"
เพราะเพียงเพราะ09
จะไม่เป็นตัวอักษรที่ถูกต้องจำนวนเต็ม หากนั่นไม่ใช่พฤติกรรมที่คุณต้องการคุณสามารถเพิ่ม10
เป็นอาร์กิวเมนต์ที่สองInteger
ได้ดังนั้นตัวเลขจะถูกตีความว่าเป็นฐาน 10 เสมอ
#to_i
นั้นเสียเกินไปเพราะความยินยอม
Integer()
เป็นที่ยอมรับเพราะInteger ()
คุณรู้ว่าสิ่งใดก็ตามที่ Ruby พิจารณาว่าเป็นตัวอักษรจำนวนเต็มจะได้รับการยอมรับและทุกอย่างอื่นจะถูกปฏิเสธ การทำซ้ำสิ่งที่ภาษาให้คุณนั้นมีกลิ่นรหัสที่แย่กว่าการใช้ข้อยกเว้นสำหรับการควบคุม
คุณสามารถทำหนึ่งซับ:
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
"12".match(/^(\d)+$/) # true
"1.2".match(/^(\d)+$/) # false
"dfs2".match(/^(\d)+$/) # false
"13422".match(/^(\d)+$/) # true
true
และfalse
แต่MatchData
กรณีและnil
!!
หรือใช้present?
ถ้าคุณต้องการบูลีน!!( "12".match /^(\d)+$/ )
หรือ"12".match(/^(\d)+$/).present?
(หลังต้องการ Rails / แอคทีฟซัพพอร์ท)
Ruby 2.6.0 เปิดใช้งานการแคสต์เป็นจำนวนเต็มโดยไม่เพิ่มข้อยกเว้นและจะส่งคืนnil
หากการแคสต์ล้มเหลว และเนื่องจากnil
พฤติกรรมส่วนใหญ่false
ใน Ruby คุณสามารถตรวจสอบจำนวนเต็มดังนี้:
if Integer(my_var, exception: false)
# do something if my_var can be cast to an integer
end
class String
def integer?
Integer(self)
return true
rescue ArgumentError
return false
end
end
is_
ขึ้นต้นด้วย ผมพบว่าวิธีการโง่ questionmark ผมชอบมากดีกว่า"04".integer?
"foo".is_integer?
"01"
และเช่นนั้นinteger?("a string")
FTL
String#integer?
เป็นชนิดของโปรแกรมแก้ไขทั่วไปที่ Ruby coder ทุกคนและลูกพี่ลูกน้องของพวกเขาชอบที่จะเพิ่มเข้าไปในภาษานำไปสู่ codebases ที่มีการใช้งานที่ไม่เข้ากันสามอย่างที่แตกต่างกันและการแตกที่ไม่คาดคิด ฉันเรียนรู้วิธีนี้อย่างหนักในโครงการทับทิมขนาดใหญ่
วิธีที่ดีที่สุดและเรียบง่ายคือการใช้ 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?
วิธีที่ง่ายกว่านั้นก็คือ
/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true
def isint(str)
return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/)
end
โดยส่วนตัวฉันชอบวิธีการยกเว้นแม้ว่าฉันจะทำให้มันสั้นกว่า:
class String
def integer?(str)
!!Integer(str) rescue false
end
end
อย่างไรก็ตามอย่างที่คนอื่น ๆ ได้บอกไปแล้วมันไม่ได้ผลกับสตริงของ Octal
Ruby 2.4 มีRegexp#match?
: (พร้อม?
)
def integer?(str)
/\A[+-]?\d+\z/.match? str
end
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
สิ่งนี้อาจไม่เหมาะกับทุกกรณีโดยใช้อย่างง่าย:
"12".to_i => 12
"blah".to_i => 0
อาจทำเพื่อบางคน
ถ้าเป็นตัวเลขไม่ใช่ 0 มันจะส่งคืนตัวเลข ถ้ามันคืนค่า 0 มันจะเป็นสตริงหรือ 0
"12blah".to_i => 12
แต่ก็ไม่แนะนำให้ใช้ตั้งแต่ นี่อาจทำให้เกิดปัญหาในสถานการณ์แปลก ๆ
นี่คือทางออกของฉัน:
# /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สำหรับการค้นหาตัวเลขในสตริงใด ๆ คุณสามารถทดสอบการแสดงออก regex ของคุณและผลที่http://rubular.com/IntegerRegex
เพื่อหลีกเลี่ยงการจัดสรรหน่วยความจำที่ไม่จำเป็นทุกครั้งที่เราใช้ในวิธีการinteger?
เป็นวิธีที่มีคำถามที่ควรจะกลับหรือtrue
false
match
เป็นวิธีการในสตริงซึ่งตรงกับเหตุการณ์ที่เกิดขึ้นตามการแสดงออก regex nil
ได้รับในการโต้แย้งและกลับค่าที่ตรงกันหรือ!!
แปลงผลลัพธ์ของmatch
เมธอดเป็นบูลีนที่เทียบเท่าString
คลาสที่มีอยู่คือการปะของลิงซึ่งไม่ได้เปลี่ยนแปลงอะไรในฟังก์ชันของสตริงที่มีอยู่ แต่เพียงแค่เพิ่มเมธอดอื่นที่ชื่อinteger?
บนวัตถุ String ใด ๆการเพิ่มคำตอบของ @ rado เหนือคำตอบหนึ่งสามารถใช้คำสั่งที่ประกอบไปด้วยเพื่อบังคับให้กลับมาเป็นบูลีนจริงหรือเท็จโดยไม่ต้องใช้คู่เรียบ จริงอยู่ที่เวอร์ชันการปฏิเสธแบบลอจิกแบบคู่นั้นมีความหมายสั้นกว่า แต่อาจอ่านได้ยากกว่าสำหรับผู้มาใหม่ (เช่นฉัน)
class String
def is_i?
self =~ /\A[-+]?[0-9]+\z/ ? true : false
end
end
สำหรับกรณีทั่วไปเพิ่มเติม (รวมถึงตัวเลขที่มีจุดทศนิยม) คุณสามารถลองวิธีการต่อไปนี้:
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
สำหรับคำอธิบายโดยละเอียดของ regex ที่เกี่ยวข้องที่นี่ลองดูบทความในบล็อกนี้ :)
obj.is_a? String
เพราะString # to_sจะส่งคืนเองซึ่งฉันเดาว่าไม่ต้องการการประมวลผลมากเกินไปเมื่อเทียบกับการ.is_a?
โทร ด้วยวิธีนี้คุณจะโทรเพียงครั้งเดียวในสายนี้แทนที่จะเป็นหนึ่งหรือสองสาย นอกจากนี้คุณสามารถรวมโดยตรง!!
ภายในnumber?
วิธีการเพราะโดยการประชุมชื่อวิธีการที่ลงท้ายด้วย?
ควรจะส่งกลับค่าบูลีน ความนับถือ!
ฉันชอบสิ่งต่อไปนี้ตรงไปตรงมา:
def is_integer?(str)
str.to_i != 0 || str == '0' || str == '-0'
end
is_integer?('123')
=> true
is_integer?('sdf')
=> false
is_integer?('-123')
=> true
is_integer?('0')
=> true
is_integer?('-0')
=> true
ระวังให้ดี:
is_integer?('123sdfsdf')
=> true
ซับในหนึ่ง string.rb
def is_integer?; true if Integer(self) rescue false end
ฉันไม่แน่ใจว่าสิ่งนี้เกิดขึ้นเมื่อมีการถามคำถามหรือไม่ แต่สำหรับทุกคนที่สะดุดในโพสต์นี้วิธีที่ง่ายที่สุดคือ:
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?
จะทำงานกับวัตถุใด ๆ
"12".is_an_integer? == true
"not12".is_an_integer? == false
12.is_an_integer? == true