रूबी का उपयोग करते हुए एक स्ट्रिंग मूल रूप से उद्धरण में पूर्णांक है तो कैसे परीक्षण करें


128

मुझे एक फ़ंक्शन की आवश्यकता है is_an_integer, जहां

  • "12".is_an_integer? सच लौटाता है।
  • "blah".is_an_integer? झूठा लौटता है।

मैं रूबी में यह कैसे कर सकता हूं? मैं एक रेगेक्स लिखूंगा लेकिन मैं मान रहा हूं कि इसके लिए एक सहायक है जिसे मैं नहीं जानता हूं।



1
नियमित अभिव्यक्ति पर निर्भर समाधानों का उपयोग करके सावधान रहें। बेंचमार्क बताते हैं कि वे नियमित कोड की तुलना में बहुत अधिक धीमी गति से चलते हैं।
टिन मैन

जवाबों:


135

आप नियमित अभिव्यक्ति का उपयोग कर सकते हैं। यहाँ @ jmm के सुझावों के साथ कार्य किया गया है।

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  

4
बुरा नहीं। रूबी में आप आम तौर पर "रिटर्न" कीवर्ड को छोड़ देते हैं अगर फ़ंक्शन में अंतिम अभिव्यक्ति में रिटर्न मूल्य उत्पन्न होता है। यह शून्य का पूर्णांक मान भी लौटाएगा, आप शायद एक बूलियन चाहते हैं, इसलिए कुछ !! (str = ~ / ^ [- +]! [0-9] + $ /) ऐसा करेंगे। तब आप इसे स्ट्रिंग में जोड़ सकते हैं और तर्क छोड़ सकते हैं, "स्ट्र" के बजाय "सेल्फ" का उपयोग कर सकते हैं, और फिर आप नाम को "is_i?" में बदल सकते हैं। ...
जनम

2
धन्यवाद! रूबी सम्मेलनों और प्रथाओं के बारे में मेरे पास कोई सुराग नहीं है। मैंने सिंटैक्स को देखने के लिए रूबी और नियमित अभिव्यक्तियों पर एक त्वरित Google किया, हाथ पर समस्या को लागू करने के लिए रेगेक्स को बदल दिया, और इसका परीक्षण किया। यह वास्तव में बहुत साफ है .. मुझे अधिक खाली समय होने पर इसे अधिक समय देना पड़ सकता है।
राडो

आपको सही विचार मिला है, लेकिन यह बाइनरी या हेक्स शाब्दिकों से मेल नहीं खाता (नीचे मेरा संपादित समाधान देखें)।
सारा मेई

16
दो टिप्पणियाँ। आप निर्माण के /regexp/ === selfबजाय उपयोग कर सकते हैं !!(self =~ /regexp/)। आप इसके बजाय चरित्र वर्ग 'd' का उपयोग कर सकते हैं[0-9]
wich

1
पूर्णांक के लिए सबसे सरल
रीजैक्स

169

खैर, यहाँ एक आसान तरीका है:

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

27
"01" .to_i.to_s! = "01"
sepp2k

2
आप के self.to_i.to_s == selfसाथ बदल नहीं सकता Integer self rescue false?
मेरेडिथ एल। पैटरसन

5
आप कर सकते हैं, लेकिन यह बुरा रूप होगा। आप नियंत्रण प्रवाह के रूप में अपवादों का उपयोग नहीं करते हैं, और किसी के कोड में कभी भी "बचाव असत्य" (या "बचाव सही") नहीं होना चाहिए। कुछ सरल gsub'ing ओपी द्वारा निर्दिष्ट नहीं किए गए किनारे के मामलों के लिए मेरे समाधान का काम करेंगे।
सारा मेई

4
मुझे पता है कि बहुत से लोग इसका उपयोग करते हैं, और यह निश्चित रूप से सौंदर्यवादी रूप से मनभावन है। मेरे लिए हालांकि यह एक संकेत है कि कोड को पुनर्गठन की आवश्यकता है। यदि आप एक अपवाद की अपेक्षा कर रहे हैं ... यह अपवाद नहीं है।
सारा मेई

2
मैं सहमत हूं कि अपवादों को नियंत्रण प्रवाह के रूप में उपयोग नहीं किया जाना चाहिए। मुझे नहीं लगता कि आवश्यकता यह है कि डेवलपर उन्मुख संख्याओं को मान्यता दी जाए। गैर-प्रोग्रामर स्थितियों में जिन्हें बग के रूप में देखा जा सकता है, विशेष रूप से अग्रणी शून्य और ऑक्टल के आसपास संभव भ्रम को देखते हुए। इसके अलावा to_i के अनुरूप नहीं है। आपका कोड "-0123" केस को हैंडल नहीं करता है। एक बार जब आप उस मामले को संभाल लेते हैं, तो आपको ऑक्टल के लिए अलग से रेक्सएक्सपी की आवश्यकता नहीं होती है। आप बस "किसी भी?" का उपयोग करके आगे कर सकते हैं। आपके फ़ंक्शन का एकमात्र कथन "[/ re1 /, / re2 /, / re3 /] हो सकता है। {{| {| re | self = ~ re}", यदि कोई क्लॉज़ या रिटर्न नहीं है।
शाम

67

आप उपयोग कर सकते हैं Integer(str)और देख सकते हैं कि क्या यह उठता है:

def is_num?(str)
  !!Integer(str)
rescue ArgumentError, TypeError
  false
end

यह ध्यान दिया जाना चाहिए कि जबकि यह सच है के लिए लौटा "01", यह नहीं है "09", सिर्फ इसलिए 09कि एक वैध पूर्णांक शाब्दिक नहीं होगा। यदि वह व्यवहार नहीं है जिसे आप चाहते हैं, तो आप 10दूसरे तर्क के रूप में जोड़ सकते हैं Integer, इसलिए संख्या को हमेशा आधार 10 के रूप में व्याख्या किया जाता है।


39
यार ... सिर्फ एक नंबर कन्वर्ट करने के लिए एक अपवाद भड़काने? अपवाद नियंत्रण प्रवाह नहीं हैं।
सारा मेई

29
वे नहीं हैं, लेकिन दुर्भाग्य से यह रूबी में एक स्ट्रिंग के "पूर्णता" का निर्धारण करने के लिए विहित तरीका है। #to_iयह अनुमति के कारण उपयोग करने के तरीके अभी बहुत टूट चुके हैं।
अवीडी

17
ऐसा सोचने वालों के लिए, Integer ("09") मान्य नहीं है क्योंकि "0" इसे अष्टाध्यायी बनाता है, और 9 एक वैध अष्टक संख्या नहीं है। osdir.com/ml/lang.ruby.general/2002-08/msg00247.html
एंड्रयू ग्रिम

20
सारा: आप एक Regex का उपयोग कर सकते हैं, लेकिन सभी मामलों को संभालने के लिए जो रूबी पूर्णांक (नकारात्मक संख्या, हेक्स, अष्टक, अंडरस्कोर जैसे 1_000_000) को पार्स करते समय करता है यह एक बहुत बड़ा Regex होगा और गलत करने में आसान होगा। Integer()विहित है क्योंकि Integer ()आप निश्चित रूप से जानते हैं कि रूबी को पूर्णांक शाब्दिक मानने वाली कोई भी चीज़ स्वीकार की जाएगी, और बाकी सब अस्वीकार कर दिया जाएगा। डुप्लिकेटिंग जो भाषा आपको पहले से देती है वह यकीनन नियंत्रण के लिए अपवादों का उपयोग करने की तुलना में एक बदतर कोड गंध है।
अवधी

9
@ राडो तो पहिया को मजबूत कर रहा है।
sepp2k

24

आप एक लाइनर कर सकते हैं:

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

1
विषय "अपवाद के रूप में नियंत्रण प्रवाह" के संबंध में: चूंकि हम नहीं जानते हैं कि हाथ में विधि का उपयोग कैसे किया जाता है, हम वास्तव में यह नहीं आंक सकते हैं कि अपवाद फिट होगा या नहीं। यदि स्ट्रिंग इनपुट है और यह पूर्णांक होना आवश्यक है, तो एक गैर पूर्णांक प्रदान करना अपवाद का वारंट करेगा। हालाँकि तब शायद हैंडलिंग एक ही विधि में नहीं है और हम शायद केवल Integer (str) .times {> i करेंगे मैं} या जो कुछ भी कहते हैं।
रॉबर्ट क्लेमे

24
"12".match(/^(\d)+$/)      # true
"1.2".match(/^(\d)+$/)     # false
"dfs2".match(/^(\d)+$/)    # false
"13422".match(/^(\d)+$/)   # true

4
यह वापस नहीं करता है trueऔर falseलेकिन MatchDataउदाहरणों औरnil
स्टीफन

यह वह नहीं है जो इसे लौटाता है, लेकिन अगर यह मेल खाता है
Maciej Krasowski

5
यदि आपको बूलियन या (बाद में आवश्यक रेल / एक्टिविस्पोर्ट की आवश्यकता है) के साथ इसे लपेटें !!या उपयोग करेंpresent?!!( "12".match /^(\d)+$/ )"12".match(/^(\d)+$/).present?
mahemoff

1
यह नियमित अभिव्यक्ति साइन इन नहीं करती है: नकारात्मक संख्याएँ पूर्णांक संख्याएँ भी होती हैं। अब आप मान्य प्राकृतिक संख्या या शून्य के लिए परीक्षण कर रहे हैं ।
जोकेम शुल्नेक्लोपर

13

रूबी 2.6.0 एक अपवाद को बढ़ाए बिना एक पूर्णांक के लिए कास्टिंग सक्षम बनाता है , और nilअगर कलाकार विफल रहता है तो वापस आ जाएगा । और चूंकि nilज्यादातर falseरूबी की तरह व्यवहार करता है , आप आसानी से पूर्णांक की तरह जांच कर सकते हैं:

if Integer(my_var, exception: false)
  # do something if my_var can be cast to an integer
end

8
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. वस्तु उन्मुख, याय।

1
+1 # नामकरण के लिए।? -1
Avdi

1
और कहां जाएगा? integer?("a string")FTL।
अगस्त लिलियास

2
String#integer?आम पैच की तरह है कि हर रूबी कोडर और उनके चचेरे भाई को भाषा में जोड़ना पसंद करते हैं, तीन अलग-अलग सूक्ष्म रूप से असंगत कार्यान्वयन और अप्रत्याशित टूटने के साथ कोडबेस की ओर जाता है। मैंने इसे बड़ी रूबी परियोजनाओं पर कठिन तरीके से सीखा।
अवधी

उपरोक्त के रूप में समान टिप्पणी: अपवादों का उपयोग नियंत्रण प्रवाह के लिए नहीं किया जाना चाहिए।
सारा मेई

नकारात्मक पक्ष: यह समाधान एक रूपांतरण को बर्बाद कर रहा है।
रॉबर्ट क्लेमे

7

सबसे अच्छा और सरल तरीका उपयोग कर रहा है 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


मुझे खुशी है कि मैंने आपका जवाब देखा। अन्यथा मुझे "फ्लोट" की आवश्यकता होने पर "इंटेगर" के साथ चला जाता।
जेफ ज़िकोविक

यह सरल लेकिन सबसे अच्छा जवाब है! हम वास्तव में ज्यादातर मामलों में स्ट्रिंग वर्ग को फैंसी पैच की आवश्यकता नहीं है। यह मेरे लिए सबसे अच्छा काम करता है!
अन न्गुयेन

(फ्लोट (मूल्य) बचाव झूठ)? फ्लोट (मूल्य) .to_s == मूल्य? फ्लोट (मूल्य): पूर्णांक (मूल्य): मूल्य
ओक्लिव

6

मैं पसंद करता हूं:

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?

4

बहुत सरल तरीका हो सकता है

/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true

3
  def isint(str)
    return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/)
  end

कोड केवल उत्तर बहुत उपयोगी नहीं हैं। इसके बजाय यह कैसे काम करता है और यह उपयुक्त उत्तर क्यों है, इसका स्पष्टीकरण प्रदान करें। हम भविष्य के लिए शिक्षित करना चाहते हैं इसलिए समाधान को समझा जाता है, तत्काल प्रश्न को हल नहीं करना।
द टीन मैन

3

व्यक्तिगत रूप से मुझे अपवाद दृष्टिकोण पसंद है, हालांकि मैं इसे थोड़ा और अधिक बनाऊंगा:

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

हालाँकि, जैसा कि अन्य पहले ही बता चुके हैं, यह ऑक्टल स्ट्रिंग्स के साथ काम नहीं करता है।


2

रूबी 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

2

यह सरल रूप से उपयोग करने वाले सभी मामलों के लिए उपयुक्त नहीं हो सकता है:

"12".to_i   => 12
"blah".to_i => 0

कुछ के लिए भी कर सकते हैं।

यदि यह एक संख्या है और 0 नहीं है तो यह एक नंबर लौटाएगा। यदि यह 0 देता है तो यह या तो एक स्ट्रिंग है या 0 है।


11
काम करता है, लेकिन यह अनुशंसित नहीं है, क्योंकि "12blah".to_i => 12। इससे अजीब परिदृश्यों में कुछ परेशानी हो सकती है।
rfsbraz

2

यहाँ मेरा समाधान है:

# /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/ पर अपने regex भावों और परिणामों का परीक्षण कर सकते हैं ।
  • हम IntegerRegexअनावश्यक मेमोरी आवंटन से बचने के लिए इसे निरंतर रूप से सहेजते हैं, हम इसे विधि में उपयोग करते हैं।
  • integer?एक पूछताछ विधि है जो वापस आनी चाहिए trueया false
  • match स्ट्रिंग पर एक विधि है जो तर्क में दिए गए regex अभिव्यक्ति के अनुसार घटनाओं से मेल खाती है और मिलान किए गए मानों को वापस करती है या nil
  • !! का परिणाम परिवर्तित करता है matchविधि को समतुल्य बूलियन में ।
  • और मौजूदा Stringकक्षा में विधि की घोषणा करना बंदर का पैचिंग है, जो मौजूदा स्ट्रिंग फ़ंक्शंस में कुछ भी नहीं बदलता है, लेकिन बस integer?किसी भी स्ट्रिंग ऑब्जेक्ट पर नामित एक और तरीका जोड़ता है ।

1
क्या आप कृपया इसमें थोड़ी व्याख्या जोड़ सकते हैं?
स्टेफ

@stef - मैंने भी यही किया है। कृपया मुझे बताएं कि क्या आपके पास अभी भी कोई प्रश्न है।
सचिन

1

@ राडो के उत्तर पर एक के ऊपर एक विस्तार करने से भी एक द्विअर्थी कथन का उपयोग किया जा सकता है ताकि डबल बैंग्स के उपयोग के बिना सच्चे या झूठे बुलियन की वापसी के लिए मजबूर किया जा सके। दी गई, डबल लॉजिकल निगेटिव वर्जन अधिक चर्चित है, लेकिन शायद नए लोगों (मेरे जैसे) के लिए पढ़ना कठिन है।

class String
  def is_i?
     self =~ /\A[-+]?[0-9]+\z/ ? true : false
  end
end

इस बात पर विचार करें कि नियमित अभिव्यक्ति का उपयोग रूबी को बहुत अधिक काम करने के लिए मजबूर करता है यदि यह एक लूप में उपयोग किया जाता है तो यह कोड को धीमा कर देगा। एंकरिंग से अभिव्यक्ति में मदद मिलती है, लेकिन रेगेक्स अभी भी काफी धीमा है।
द टीन मैन

1

अधिक सामान्यीकृत मामलों के लिए (दशमलव बिंदु वाले नंबर सहित), आप निम्न विधि आज़मा सकते हैं:

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

यहां शामिल रेक्सक्स की विस्तृत व्याख्या के लिए, इस ब्लॉग लेख की जाँच करें :)


कॉल करने के लिए आवश्यक नहीं है obj.is_a? Stringक्योंकि स्ट्रिंग # to_s स्वयं वापस आ जाएगा, जो मुझे लगता है कि .is_a?कॉल की तुलना में बहुत अधिक प्रसंस्करण की आवश्यकता नहीं है । इस तरह, आप इस लाइन में एक या दो के बजाय केवल एक कॉल करेंगे। इसके अलावा, आप सीधे विधि के !!अंदर शामिल कर सकते हैं number?, क्योंकि सम्मेलन द्वारा, एक विधि का नाम जो समाप्त होता है ?, एक बूलियन मान वापस करने के लिए माना जाता है। सादर!
जियोवानी बेनुसी

-1

मुझे निम्नलिखित पसंद है, सीधे आगे:

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

-2

में एक लाइनर string.rb

def is_integer?; true if Integer(self) rescue false end

-3

मुझे यकीन नहीं है कि जब यह सवाल पूछा गया था तो यह आसपास था लेकिन किसी के लिए भी जो इस पद पर ठोकर खाता है, सबसे सरल तरीका है:

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
मार्कर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.