Bir işleve ihtiyacım var is_an_integer, nerede
"12".is_an_integer?true döndürür."blah".is_an_integer?yanlış döndürür.
Bunu Ruby'de nasıl yapabilirim? Bir normal ifade yazarım ama bunun için farkında olmadığım bir yardımcı olduğunu varsayıyorum.
Bir işleve ihtiyacım var is_an_integer, nerede
"12".is_an_integer? true döndürür."blah".is_an_integer? yanlış döndürür.Bunu Ruby'de nasıl yapabilirim? Bir normal ifade yazarım ama bunun için farkında olmadığım bir yardımcı olduğunu varsayıyorum.
Yanıtlar:
Normal ifadeler kullanabilirsiniz. İşte @ janm'ın önerileri ile işlev.
class String
def is_i?
!!(self =~ /\A[-+]?[0-9]+\z/)
end
end
@Wich'in yorumuna göre düzenlenmiş bir sürüm:
class String
def is_i?
/\A[-+]?\d+\z/ === self
end
end
Yalnızca pozitif sayıları kontrol etmeniz gerektiğinde
if !/\A\d+\z/.match(string_to_check)
#Is not a positive number
else
#Is all good ..continue
end
/regexp/ === selfyerine kullanabilirsiniz !!(self =~ /regexp/). Sen karakter sınıfını '\ d' yerine kullanabilirsiniz[0-9]
İşte kolay yol:
class String
def is_integer?
self.to_i.to_s == self
end
end
>> "12".is_integer?
=> true
>> "blah".is_integer?
=> false
Dizeyi dönüştürmek için bir istisnayı tetikleyen çözümlere katılmıyorum - istisnalar akış kontrolü değildir ve siz de bunu doğru şekilde yapabilirsiniz. Bununla birlikte, yukarıdaki çözümüm 10 tabanlı olmayan tam sayılarla ilgilenmiyor. İşte istisnalara başvurmadan yapmanın yolu:
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 == selfile Integer self rescue false?
Kullanabilir Integer(str)ve yükseltip yükseltmediğini görebilirsiniz:
def is_num?(str)
!!Integer(str)
rescue ArgumentError, TypeError
false
end
Bunun için doğru dönmese de "01", bunun için değil "09", çünkü 09geçerli bir tamsayı değişmez değeri olmayacağına dikkat edilmelidir. İstediğiniz davranış bu değilse, 10ikinci argüman olarak ekleyebilirsiniz Integer, böylece sayı her zaman 10 tabanı olarak yorumlanır.
#to_i, izin verilebilirliği nedeniyle çok bozuk.
Integer()bu kurallara uygundur çünkü Integer ()Ruby'nin tamsayı olarak gördüğü her şeyin kabul edileceğini ve diğer her şeyin reddedileceğini kesin olarak bilirsiniz. Dilin size zaten verdiklerini kopyalamak, kontrol için istisnalar kullanmaktan muhtemelen daha kötü bir kod kokusu.
Tek bir astar yapabilirsiniz:
str = ...
int = Integer(str) rescue nil
if int
int.times {|i| p i}
end
ya da
int = Integer(str) rescue false
Ne yapmaya çalıştığınıza bağlı olarak, doğrudan rescue cümlesiyle bir başlangıç bitiş bloğu da kullanabilirsiniz:
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
trueve falseancak MatchDataörneklerini venil
!!veya kullanım present?Eğer bir boolean gerekiyorsa !!( "12".match /^(\d)+$/ )veya "12".match(/^(\d)+$/).present?(ikincisi gerektiren Raylar / ActiveSupport)
Ruby 2.6.0, bir istisna oluşturmadan bir tamsayıya çevrim yapılmasını sağlar ve çevrimnil başarısız olursa geri döner . Beri nilçoğunlukla gibi davranır falseRuby, bunu kolaylıkla gibi bir tamsayı kontrol edebilirsiniz:
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_. Bunu soru işareti yöntemlerinde aptalca buluyorum, "04".integer?daha çok seviyorum "foo".is_integer?."01"böyle geçer .integer?("a string")FTL.
String#integer?her Ruby kodlayıcısının ve kuzeninin dile eklemeyi sevdiği türden bir yamadır, bu da üç farklı ince uyumsuz uygulama ve beklenmedik bozulmalara sahip kod tabanlarına yol açar. Bunu büyük Ruby projelerinde zor yoldan öğrendim.
En iyi ve basit yol kullanmaktır 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
IntegerAyrıca iyi ama dönecektir 0içinInteger nil
Tercih ederim:
yapılandırma / başlatıcılar / string.rb
class String
def number?
Integer(self).is_a?(Integer)
rescue ArgumentError, TypeError
false
end
end
ve sonra:
[218] pry(main)> "123123123".number?
=> true
[220] pry(main)> "123 123 123".gsub(/ /, '').number?
=> true
[222] pry(main)> "123 123 123".number?
=> false
veya telefon numarasını kontrol edin:
"+34 123 456 789 2".gsub(/ /, '').number?
Çok daha basit bir yol olabilir
/(\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
Şahsen istisna yaklaşımını seviyorum, ancak bunu biraz daha özlü yapsam da:
class String
def integer?(str)
!!Integer(str) rescue false
end
end
Ancak, diğerlerinin daha önce de belirttiği gibi, bu Sekizli dizelerle çalışmaz.
Ruby 2.4'te Regexp#match?: (a ile ?)
def integer?(str)
/\A[+-]?\d+\z/.match? str
end
Daha eski Ruby sürümleri için Regexp#===. Durum eşitliği operatörünün doğrudan kullanımından genellikle kaçınılması gerekse de, burada çok temiz görünüyor:
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
Bu, aşağıdakileri kullanarak tüm durumlar için uygun olmayabilir:
"12".to_i => 12
"blah".to_i => 0
bazıları için de yapabilir.
0 değilse ve bir sayı ise, bir sayı döndürür. 0 döndürürse, bu bir dizedir veya 0'dır.
"12blah".to_i => 12. Bu, garip senaryolarda bazı sorunlara neden olabilir.
İşte benim çözümüm:
# /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
Ve işte şu şekilde çalışıyor:
/^(\d)+$/olduğu regex herhangi dizede basamak bulmak için ifade. Normal ifade ifadelerinizi ve sonuçlarınızı http://rubular.com/ adresinde test edebilirsiniz .IntegerRegexYöntemde her kullandığımızda gereksiz bellek tahsisini önlemek için sabit olarak kaydederiz.integer?trueveya dönmesi gereken sorgulayıcı bir yöntemdir false.matchbağımsız değişkendeki verilen normal ifade ifadesine göre oluşumlarla eşleşen ve eşleşen değerleri veya döndüren dize üzerinde bir yöntemdir nil.!!matchyöntemin sonucunu eşdeğer boolean'a dönüştürür.Stringsınıfta yöntemin bildirilmesi, mevcut String işlevlerinde hiçbir şeyi değiştirmeyen, ancak yalnızca integer?herhangi bir String nesnesinde adlandırılmış başka bir yöntem ekleyen maymun yamasıdır .@ Rado'nun yukarıdaki cevabını genişletmek, çift patlama kullanmadan doğru veya yanlış boolelerin geri dönüşünü zorlamak için üçlü bir ifade de kullanabilir. Kabul edildiğinde, çifte mantıksal olumsuzlama versiyonu daha kısa ama muhtemelen yeni gelenler için (benim gibi) okuması daha zor.
class String
def is_i?
self =~ /\A[-+]?[0-9]+\z/ ? true : false
end
end
Daha genelleştirilmiş durumlar için (ondalık noktalı sayılar dahil) aşağıdaki yöntemi deneyebilirsiniz:
def number?(obj)
obj = obj.to_s unless obj.is_a? String
/\A[+-]?\d+(\.[\d]+)?\z/.match(obj)
end
Bu yöntemi bir irb oturumunda test edebilirsiniz:
(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
Burada yer alan normal ifadenin ayrıntılı açıklaması için bu blog makalesine göz atın :)
obj.is_a? Stringçünkü dize # to_s çok fazla ile karşılaştırıldığında işlem gerektirmez tahmin, hangi kendini dönecektir .is_a?çağrı. Bu şekilde, bu hatta bir veya iki yerine yalnızca bir arama yapacaksınız. Ayrıca, doğrudan yöntemin !!içine dahil edebilirsiniz number?, çünkü kural gereği, ile biten bir yöntem adının ?bir boole değeri döndürmesi gerekir. Saygılarımızla!
Aşağıdakileri çok seviyorum:
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
Yine de dikkatli olun:
is_integer?('123sdfsdf')
=> true
Bu soru sorulduğunda bunun ortalıkta olup olmadığından emin değilim, ancak bu gönderiye rastlayan herkes için en basit yol:
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? herhangi bir nesne ile çalışacaktır.
"12".is_an_integer? == true "not12".is_an_integer? == false 12.is_an_integer? == true