سؤال

لدي سلسلة ، يقول '123', و أريد تحويله إلى 123.

وأنا أعلم أنك يمكن أن تفعل ببساطة some_string.to_i, لكن الذي يحول 'lolipops' إلى 0, التي ليس لها تأثير علي في الاعتبار.أريد أن ينفجر في وجهي عندما كنت في محاولة لتحويل شيء صالح ، مع لطيفة و مؤلمة Exception.وإلا لا أستطيع التمييز بين صالح 0 و شيء فقط لا عدد على الإطلاق.

تحرير: كنت أبحث عن طريقة قياسية من يفعل ذلك ، دون regex الخداع.

هل كانت مفيدة؟

المحلول

روبي كانت هذه الوظيفة بنيت في:

Integer('1001')                                    # => 1001  
Integer('1001 nights')  
# ArgumentError: invalid value for Integer: "1001 nights"  

كما ذكر في الجواب من قبل جوزيف بيكورارو, قد ترغب في مشاهدة سلاسل صالحة غير الأرقام العشرية ، مثل تلك التي بدأت مع 0x عرافة ، 0b الثنائية ، ويحتمل أن تكون أكثر صعبة أرقام بدءا من الصفر التي سيتم تحليلها كما الثماني.

روبي 1.9.2 وأضاف اختياري الحجة الثانية عن الرقم الأساسي أعلى من هذه المشكلة يمكن تجنبها:

Integer('23')                                     # => 23
Integer('0x23')                                   # => 35
Integer('023')                                    # => 19
Integer('0x23', 10)
# => #<ArgumentError: invalid value for Integer: "0x23">
Integer('023', 10)                                # => 23

نصائح أخرى

ربما هذا العمل:

i.to_i if i.match(/^\d+$/)

أيضا أن تكون على بينة من يؤثر أن التيار تقبل الحل قد يكون على تحليل عرافة الثماني ، و الأرقام الثنائية:

>> Integer('0x15')
# => 21  
>> Integer('0b10')
# => 2  
>> Integer('077')
# => 63

في روبي الأرقام التي تبدأ مع 0x أو 0X هي عرافة ، 0b أو 0B هي الثنائية فقط 0 هي ثماني.إذا كان هذا ليس هو السلوك المطلوب قد ترغب في الجمع بين ذلك مع بعض الحلول الأخرى التي تحقق مما إذا كانت سلسلة مباريات النمط الأول.مثل /\d+/ التعبيرات العادية ، إلخ.

آخر سلوك غير متوقع مع الحل المقبول (مع 1.8 و 1.9 هو موافق):

>> Integer(:foobar)
=> 26017
>> Integer(:yikes)
=> 26025

حتى إذا كنت غير متأكد من ما يجري تمريرها في, تأكد من إضافة .to_s.

أنا أحب مايرون الإجابة لكنها تعاني من روبي مرض "أنا لم يعد استخدام Java/C# حتى أنا لن تستخدم الميراث مرة أخرى".فتح أي فئة يمكن أن تكون محفوفة بالمخاطر و يجب أن تستخدم لماما ، خاصة عندما يكون جزء من روبي مكتبة الأساسية.أنا لا أقول لا تستخدم أي وقت مضى ، ولكن عادة ما يكون من السهل تجنب وأن هناك أفضل الخيارات المتاحة ، مثل

class IntegerInString < String

  def initialize( s )
    fail ArgumentError, "The string '#{s}' is not an integer in a string, it's just a string." unless s =~ /^\-?[0-9]+$/
    super
  end
end

ثم عندما كنت ترغب في استخدام سلسلة يمكن أن يكون هناك عدد من الواضح ما تفعله و أنت لا تضرب أي الطبقة الأساسية ، مثل

n = IntegerInString.new "2"
n.to_i
# => 2

IntegerInString.new "blob"
ArgumentError: The string 'blob' is not an integer in a string, it's just a string.

يمكنك إضافة جميع أنواع الشيكات الأخرى في تهيئة مثل التحقق من الأرقام الثنائية.... الخالشيء الرئيسي على الرغم من أن روبي للناس يجري على الناس يعني الوضوح.تسمية كائن عن طريق اسم المتغير و فئتها اسم يجعل الأمور كثيرا أوضح.

اضطررت للتعامل مع هذا في آخر المشروع و التنفيذ كان مشابهة ولكن مختلفة قليلا:

class NotAnIntError < StandardError 
end

class String
  def is_int?    
    self =~ /^-?[0-9]+$/
  end

  def safe_to_i
    return self.to_i if is_int?
    raise NotAnIntError, "The string '#{self}' is not a valid integer.", caller
  end
end

class Integer
  def safe_to_i
    return self
  end            
end

class StringExtensions < Test::Unit::TestCase

  def test_is_int
    assert "98234".is_int?
    assert "-2342".is_int?
    assert "02342".is_int?
    assert !"+342".is_int?
    assert !"3-42".is_int?
    assert !"342.234".is_int?
    assert !"a342".is_int?
    assert !"342a".is_int?
  end

  def test_safe_to_i
    assert 234234 == 234234.safe_to_i
    assert 237 == "237".safe_to_i
    begin
      "a word".safe_to_i
      fail 'safe_to_i did not raise the expected error.'
    rescue NotAnIntError 
      # this is what we expect..
    end
  end

end
someString = "asdfasd123"
number = someString.to_i
if someString != number.to_s
  puts "oops, this isn't a number"
end

ربما لا أنظف طريقة للقيام بذلك, ولكن يجب أن تعمل.

Re: كريس الجواب

التنفيذ دعونا أشياء مثل "1a" أو "b2" من خلال.ماذا عن هذا بدلا من ذلك:

def safeParse2(strToParse)
  if strToParse =~ /\A\d+\Z/
    strToParse.to_i
  else
    raise Exception
  end
end

["100", "1a", "b2", "t"].each do |number|
  begin
    puts safeParse2(number)
  rescue Exception
    puts "#{number} is invalid"
  end
end

هذه النواتج:

100
1a is invalid
b2 is invalid
t is invalid
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top