我又一次处于这种不舒服的境地,有人给我留下了一段我不懂的语言的代码片段,我必须维护它。虽然我还没有向自己介绍过Ruby,但其中的一些内容非常简单,但我还是想听听您的解释。如下所示:
words = File.open("lengths.txt") {|f| f.read }.split # read all lines of a file in 'words'?
values = Array.new(0)
words.each { |value| values << value.to_i } # looked this one up, it's supposed to convert to an array of integers, right?
values.sort!
values.uniq!
diffs = Array.new(0) # this looks unused, unless I'm missing something obvious
sum = 0
s = 0 # another unused variable
# this looks like it's computing the sum of differences between successive
# elements, but that sum also remains unused, or does it?
values.each_index { |index| if index.to_i < values.length-1 then sum += values.at(index.to_i + 1) - values.at(index.to_i) end } # could you also explain the syntax here?
puts "delta has the value of\n"
# this will eventually print the minimum of the original values divided by 2
puts values.at(0) / 2上面的脚本应该计算出列表中每两个连续元素(本质上是整数)之间的差异的平均值。我说这与它的实际功能相去甚远,或者我遗漏了一些基本的东西,这很可能是因为我没有Ruby知识,这是正确的吗?
发布于 2011-01-08 20:40:53
那家伙肯定没抓到Ruby自己。我想知道他为什么选择使用这种语言。
以下是带注释的解释:
# Yes, it reads all lines of a file in words (an array)
words = File.open("lengths.txt") {|f| f.read }.split
values = Array.new(0)
# Yes, to_i convert string into integer
words.each { |value| values << value.to_i }
values.sort!
values.uniq!
# diffs and s seem unused
diffs = Array.new(0)
sum = 0
s = 0
# The immediate line below can be read as `for(int index = 0; index < values.length; index++)`
values.each_index { |index|
# index is integer, to_i is unnecessary
if index.to_i < values.length-1 then
# The `sum` variable is used here
# Following can be rewritten as sum += values[i-1] - values[i]
sum += values.at(index.to_i + 1) - values.at(index.to_i)
end
}
puts "delta has the value of\n"
# Yes, this will eventually print the minimal of the original values divided by 2
puts values.at(0) / 2为了帮助您更好地了解“真正的”(惯用的) Ruby是什么样子,我编写了您想要的内容,并添加了一些注释
values = open("lengths.txt") do |f|
# Read it like this:
#
# Take the list of all lines in a file,
# apply a function to each line
# The function is stripping the line and turning it
# into an integer
# (This means the resultant list is a list of integers)
#
# And then sort it and unique the resultant list
#
# The eventual resultant list is assigned to `values`
# by being the return value of this "block"
f.lines.map { |l| l.strip.to_i }.sort.uniq
end
# Assign `diffs` to an empty array (instead of using Array.new())
diffs = []
values.each_index do |i|
# Syntactic sugar for `if`
# It applies the 1st part if the 2nd part is true
diffs << (values[i+1] - values[i]) if i < values.length - 1
end
# You can almost read it like this:
#
# Take the list `diffs`, put all the elements in a sentence, like this
# 10 20 30 40 50
#
# We want to inject the function `plus` in between every element,
# so it becomes
# 10 + 20 + 30 + 40 + 50
#
# The colon `:+` is used to refer to the function `plus` as a symbol
#
# Take the result of the above summation, divided by length,
# which gives us average
delta = diffs.inject(:+) / diffs.length
# `delta` should now contains the "average of differences" between
# the original `values`
# String formatting using the % operator
# No \n needed since `puts` already add one for us
puts "delta has the value of %d" % delta这绝不是在推动Ruby的真正力量,但是您可以看到为什么Ruby拥护者对表现力和东西如此热情:P
发布于 2011-01-08 21:58:08
解释+重构(删除未使用的变量,函数方法,each_cons):
# Read integer numbers from file, sort them ASC and remove duplicates
values = File.read("lengths.txt").split.map(&:to_i).sort.uniq
# Take pairwise combinations and get the total sum of partial differences
partial_diffs = values.each_cons(2).map { |a, b| b - a }.inject(0, :+)发布于 2011-01-08 19:44:16
values.each_index { |index| if index.to_i < values.length-1 then sum += values.at(index.to_i + 1) - values.at(index.to_i) end } 上面这行对连续值之间的差值求和。由于values.at(index.to_i + 1)的原因,测试index.to_i < values.length-1不会越界访问数组。
你是对的,这段代码并不能做很多事情。它只打印文件中最小值的一半。
https://stackoverflow.com/questions/4633620
复制相似问题