我正在创建一个简短的程序来查找给定数字集的平均值。这是一个程序,其基本结构首先在TI-83上用goto语句编写,所以我对这种事情的正确实践有点不确定。这是相关代码:
$sum = 0
$counter = 0
def average
puts "Input another number, or \"end\" to end."
input = gets.chomp
if input == "end"
puts $counter
puts ($sum / $counter).to_f
else
$sum += input.to_f
$counter += 1
puts $counter
average #Here the method is called again, repeating the cycle.
end
end
我不确定如何做到这一点,因为像这样构建的代码点是它可以处理不确定数量的输入,因此它重复性质。
答案 0 :(得分:5)
在具有所谓的“尾调用优化”的语言中,这种结构是循环的主要方式。然而,Ruby却没有;递归(重新输入已经输入的函数)是常用的,但不能作为简单循环的一般替代,就像在这种情况下一样。
此处,正如pvg所述,while
(或等效地,until
)循环更好:
sum = 0
counter = 0
puts "Input a number, or \"end\" to end."
input = gets.chomp
until input == "end"
sum += input.to_f
counter += 1
puts "Input another number, or \"end\" to end."
input = gets.chomp
end
puts sum / counter
或带有break
的无限循环:
sum = 0
counter = 0
loop do
puts "Input a number, or \"end\" to end."
input = gets.chomp
break if input == "end"
sum += input.to_f
counter += 1
end
puts sum / counter
但你也可以使用更多的Ruby方式:
puts 'Input numbers, or "end" to end.'
array = STDIN.each_line.lazy
.map(&:chomp)
.take_while { |line| line != "end" }
.map(&:to_f)
.to_a
puts array.inject(&:+) / array.size
或者更丑陋但内存效率更高:
puts 'Input numbers, or "end" to end.'
sum, count = *STDIN.each_line.lazy
.map(&:chomp)
.take_while { |line| line != "end" }
.inject([0, 0]) { |memo, x|
[memo[0] + x.to_f, memo[1] + 1]
}
puts sum / count
答案 1 :(得分:1)
是的,一种方法可以调用自己。这称为递归,是编程和计算机科学中非常重要的概念。
您需要的只是一个基本案例和对自己的调用。在您的示例中,基本情况是
if input == "end"
puts $counter
puts ($sum / $counter).to_f
并且重复步骤是
else
$sum += input.to_f
$counter += 1
puts $counter
average #Here the method is called again, repeating the cycle.
答案 2 :(得分:1)
这不是一个新答案,而是一个支持@ adao7000答案的插图示例。
递归可以是一个非常强大的工具。最好的例子之一是遍历嵌套数组或散列。递归允许您定义如何一次提取数据,然后在每个级别使用相同的过程 - 而无需知道有多少级别。
这是一个简单的例子:
nested_array = [
'level 1',
[
'level 2'
],
[
[
'level 3',
[
'level 4'
]
]
]
]
def print_values(element)
if element.kind_of? Array
element.each{|e| print_values(e)}
else
puts element
end
end
print_values nested_array
请注意print_values方法如何打印出当前值或将子数组传回给自己。