我尝试使用CSV来计算三个数字的平均值并将其输出到单独的文件中。特别是,打开一个文件,取第一个值(名称),然后计算接下来三个值的平均值。对文件中的每个人多次执行此操作。
这是我的Book1.csv
Tom,90,80,70
Adam,80,85,83
Mike,100,93,89
Dave,100,100,100
Rob,80,70,75
Nick,80,90,70
Justin,100,90,90
Jen,80,90,100
我试图让它输出:
Tom,80
Adam,83
Mike,94
Dave,100
Rob,75
Nick,80
Justin,93
Jen,90
我让每个人都在一个数组中,我可以使用基本的"伪"我写的代码,但它不起作用。 到目前为止,这是我的代码:
#!/usr/bin/ruby
require 'csv'
names=[]
grades1=[]
grades2=[]
grades3=[]
average=[]
i = 0
CSV.foreach('Book1.csv') do |students|
names << students.values_at(0)
grades1 << reader.values_at(1)
grades2 << reader.values_at(2)
grades3 << reader.values_at(3)
end
while i<10 do
average[i]= grades1[i] + grades2[i] + grades3[i]
i= i + 1
end
CSV.open('Book2.csv', 'w') do |writer|
rows.each { |record| writer << record }
end
while循环部分是我最关心的部分。有什么见解吗?
答案 0 :(得分:2)
如果您有要汇总的值数组,可以使用:
sum = array.inject(:+)
如果您将数据结构更改为:
grades = [ [], [], [] ]
...
grades[0] << reader.values_at(1)
然后你可以这样做:
0.upto(9) do |i|
average[i] = (0..2).map{ |n| grades[n][i] }.inject(:+) / 3
end
有多种方法可以改善您的数据结构,以上是对您的代码影响最小的方法之一。
任何时候你发现自己写作:
foo1 = ...
foo2 = ...
您应该将其识别为代码气味,并考虑如何在更好的集合中组织数据。
这是对我如何做到这一点的重写。请注意,它适用于任何数量的分数,而不是硬编码为3:
require 'csv'
averages = CSV.parse(DATA.read).map do |row|
name, *grades = *row
[ name, grades.map(&:to_i).inject(:+) / grades.length ]
end
puts averages.map(&:to_csv)
#=> Tom,80
#=> Adam,82
#=> Mike,94
#=> Dave,100
#=> Rob,75
#=> Nick,80
#=> Justin,93
#=> Jen,90
__END__
Tom,90,80,70
Adam,80,85,83
Mike,100,93,89
Dave,100,100,100
Rob,80,70,75
Nick,80,90,70
Justin,100,90,90
Jen,80,90,100