将不同数组的元素添加到一起

时间:2012-04-12 15:20:16

标签: ruby arrays csv

我尝试使用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循环部分是我最关心的部分。有什么见解吗?

1 个答案:

答案 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