如何减少if语句?
通过克里斯派恩的学习编程和编号为罗马数字转换项目。下面的代码可以工作,但是如果(和结束)语句都很糟糕。但是,当我使用elsif程序不响应(似乎冻结)。任何想法都会有帮助!如何减少if语句?
def calc input
roman_numeral = ''
while true
if input >= 1000
roman_numeral += 'M' * (input/1000)
input = input - (1000 * (input/1000))
if input <= 999 || input >= 500
roman_numeral += 'D' * (input/500)
input = input - (500 * (input/500))
if input <= 499 || input >= 100
roman_numeral += 'C' * (input/100)
input = input - (100 * (input/100))
if input <= 99 || input >= 50
roman_numeral += 'L' * (input/50)
input = input - (50 * (input/50))
if input <= 49 || input >= 10
roman_numeral += 'X' * (input/10)
input = input - (10 * (input/10))
if input <= 9 || input >= 5
roman_numeral += 'V' * (input/5)
input = input - (5 * (input/5))
if input <= 4 || input >= 1
roman_numeral += 'I' * (input/1)
input = input - (1 * (input/1))
puts roman_numeral
break
end
end
end
end
end
end
end
end
end
puts 'Give me a number, any number:'
input = gets.chomp.to_i
calc(input)
这是方便的是使用该方法Enumerable#find以与阵列:
ARR = [[1000,'M'], [ 500,'D'], [100,'C'], [50,'L'], [10,'X'], [5,'V'], [1,'I']]
def which(input)
ARR.find { |v,_| input >= v }
end
which(2) #=> [1, "I"]
which(7) #=> [5, "V"]
which(17) #=> [10, "X"]
which(77) #=> [50, "L"]
which(777) #=> [500, "D"]
which(7777) #=> [1000, "M"]
假设你的整数转换为罗马数字,考虑利用该方法Fixnum#divmod的。假设整数为2954
和你已经确定有两个"M"
的和一个"D"
(所以你的罗马数字字符串的开头是"MMD"
),以及454
被遗留下来的。然后:
c, rem = 454.divmod(100)
#=>[4, 54]
c #=> 4
rem #=> 54
告诉你有四个"C"
的与54
遗留下来的。
四"C"
的写"CD"
(不"CCCC"
),然而,您可能要使用的哈希如下列:
REP = {..., "C"=>["C", "CC", "CCC", "CD"], ...}
到"C"
数转换的一个罗马数字。在这里你可以附加REP["C"][4-1] #=> "CD"
到"MMD"
:"MMD" << "CD" #=> "MMDCD"
。
卡里 - 感谢您的快速和详细的反应。在较高的层面上它是有道理的,但是我认为在我能够正确实施你所建议的方法之前,我有一段路要走。虽然我已经得到了你:对初学者红宝石主义者的资源有什么建议?正如我在文章中提到的,我现在正在通过Pragmatic的Programming for Beginners,我很享受。任何其他建议将不胜感激。 – cmrnwllsbrn
以下是一些可能性:[Ruby学习中的核心Ruby课程](http://rubylearning.org/classes/),[Code School](https://www.codeschool.com/courses/try-ruby)以及那些列于[iwantolearnruby](http://iwanttolearnruby.com/)。 –
从卡里Swoveland答案就是减少你的if
块嵌套一个很好的方式。
他的答案告诉你哪个数字随之而来的,而不是有多少(在你的代码)。绑在一起,它以自然的方式是一个递归函数调用:
class Romans
def self.calc(input, acc = "")
raise ArgumentError.new("Roman Numerals must be positve") if input < 0
raise ArgumentError.new("Roman Numerals must be integers") if ! input.is_a? Integer
return acc if input == 0
amount, numeral = which(input)
acc += numeral
input -= amount
calc(input, acc)
end
@@ARR = [[1000,'M'], [ 500,'D'], [100,'C'], [50,'L'], [10,'X'], [5,'V'], [1,'I']]
def self.which(input)
@@ARR.find { |v,_| input >= v }
end
end
在使用中:
pry(main)> (1..10).each{|i| puts "#{i}=> #{Romans.calc(i)}"}
1=> I
2=> II
3=> III
4=> IIII
5=> V
6=> VI
7=> VII
8=> VIII
9=> VIIII
10=> X
pry(main)> [Random.rand(1..100000)].each{|i| puts "#{i}=> #{Romans.calc(i)}"}
63124=> MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMCXXIIII
注意Ruby没有TCO,等会吹堆栈足够大数字 - 但如果您需要800万的罗马数字版本,您可能需要编写一些新的字母。
克里斯 - 感谢您的回复。正如瓦特卡里的回应一样,这很有道理,但是我认为在我能够利用你的方法之前,我还有一点距离。这里总共noob。无论如何,谢谢! – cmrnwllsbrn
下面是使用字符串乘法的一个。例如:( 'M' ×3)= 'MMM'
def to_roman(number)
raise 'Must use positive numbers.' if number <= 0
roman = ''
roman << 'M' * (number /1000)
roman << 'D' * (number % 1000/500)
roman << 'C' * (number % 500/100)
roman << 'L' * (number % 100/ 50)
roman << 'X' * (number % 50/ 10)
roman << 'V' * (number % 10/ 5)
roman << 'I' * (number % 5/ 1)
roman
end
puts to_roman(1234) # <-- test
参考:由Chris松
情况下输入学习编程第二; 当1..4罗马数字+ = '我' *(输入/ 1); ... 当5..9罗马数字+ = 'V' *(输入/ 5); ... –