2014-01-09 77 views
0

我想确保输入的罗马数字是有效的。我的策略是从第一个或第二个字符开始,如果字符串之后的任何内容都无效,那么我告诉他们重新输入他们的号码。如果我这样做,我需要为D,CD,C,XC,L,XL,X,IX,V,IV和I.创造一个条件。我写下这种条件语句的最佳方式是粘贴的方式,还是有更漂亮的方法?if语句的条件太多?

string = "CMCMD" 
integer_num = 0 

if string[0..1] = "CM" 
    if string[2..-1].include? "M" || string[2..-1].include? "CD" || string[2..-1].include? "D" || string[2..-1].include "CM" || string[2..-1].include? "C" 
    puts "This is invalid. Please enter your roman numeral correctly." 
    else 
    add 900 to integer_num and slice CM off the beginning of the string. 
    end 
end 

我看了看文档,并在S.O几件事情像this one

回答

3

尝试下面使用Enumerable#any?

if ["M","CD","D","CM","C"].any?{|e| string[2..-1].include? e } 

ary = %w(M CD D CM C) 
if ary.any?(&string[2..-1].method(:include?)) 
+0

谢谢!那个好漂亮。将在10分钟内接受答案。 – user3138341

1

这是我个人的库中的方法罗马数字字符串转换成一个数字。在你的问题中你不清楚你认为哪种字符串是无效的。我的方法试图最大限度地理解罗马字符。

class String 
    RomanToI = {"i"=>1, "v"=>5, "x"=>10, "l"=>50, "c"=>100, "d"=>500, "m"=>1000} 
    def roman_to_i! 
    prev = 1000 
    downcase.each_char.inject(0) do |i, d| 
     raise "Invalid string as Roman numeral" unless d = RomanToI[d] 
     (d <= prev) ? prev = d : i -= (prev * 2) 
     i += d 
    end 
    end 
end 

"mmxiv".roman_to_i! # => 2014 
"a".roman_to_i! # => Invalid string as Roman numeral. 
+1

这是非常令人印象深刻的。我甚至没有完全理解你的代码,sawa,但它在少量代码中工作的事实非常酷。 – user3138341

0
(['M', 'D', 'C'] & string[2..-1].chars).any? 

有没有必要检查string[2..-1]'CD',如'CD'可以不存在,除非“C”和“D”也存在。相同的'CM'

string的第一部分和第二部分确实应该是变量。也许做这样的事情:

cases = {'CM' => {suffix: 'CMD', illegal: ['M', 'D', 'C']}, 
     'CD' => {...}, 
     ...} 

def invalid?(str, illegal) 
    (str.chars & illegal).any? 
end 

def check_all(cases) 
    cases.each do |c, v| 
    if invalid?(v[:suffix], v[:illegal]) 
     ... 
    end 
    end 
end