我正在创建一个简短的程序来查找给定数字集的平均值.这是一个程序,其基本结构首先在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
Run Code Online (Sandbox Code Playgroud)
我不确定如何做到这一点,因为像这样构建的代码点是它可以处理不确定数量的输入,因此它重复性质.
在具有所谓的"尾部调用优化"的语言中,这种结构是循环的主要方式.然而,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
Run Code Online (Sandbox Code Playgroud)
或者是一个无限循环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
Run Code Online (Sandbox Code Playgroud)
但是你也可以使用更多的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
Run Code Online (Sandbox Code Playgroud)
或者更丑陋但内存效率更高:
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
Run Code Online (Sandbox Code Playgroud)