0

CSVを使用して3つの数値の平均を計算し、それを別のファイルに出力しようとしています。特に、1つのファイルを開き、最初の値(名前)を取得してから、次の3つの値の平均を計算します。ファイル内の各人に対してこれを複数回実行します。

これが私の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ループの部分は、私が最も関心を持っている部分です。何か洞察はありますか?

4

1 に答える 1

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

データ構造を改善するにはさまざまな方法がありますが、上記はコードへの影響が最も少ない方法の1つです。

あなたが自分で書いていることに気付いたときはいつでも:

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
于 2012-04-12T15:25:41.807 に答える