2017-03-18 12 views
1

Rubyを初めて使用していますが、いくつかの要素を計算しようとしている間に問題が発生しました。CSVファイルの要素を計算する

私は同じヘッダーで6つのCSVファイルを持っています。質問は、支払われた月ごとの合計支払い額を調べる方法です。ここで

01-test.csv

Payment date,Payable month,House,Apartment,Amount of payment 
2014-09-14,2014-08,Panel,84,5839.77 
2014-09-14,2014-08,Brick,118,4251.63 
2014-09-14,2014-08,Brick,97,471.5 
2014-09-14,2014-08,Panel,53,236.22 
2014-09-14,2014-08,Panel,83,4220.77 
....... 

02-test.csv

Payment date,Payable month,House,Apartment,Amount of payment 
2014-10-01,2014-08,Brick,34,1522.59 
2014-10-01,2014-08,Brick,117,1285.57 
2014-10-01,2014-08,Brick,136,1925.97 
2014-10-01,2014-08,Brick,24,1032.95 
2014-10-01,2014-08,Brick,113,957.01 
....... 

私のコードは次のとおりです。任意のヒントについて

def create_month_array(payments) 
    months = [] 
    months = payments.uniq { |a| a[:payed_for] 
    months 
end 
def payed_for_each_month(payments, months) 
    sums = Array.new(months.length){|a| a = 0} 
    months.each{|a| 
     if(a[:payed_for] == payments.each{|x| x[:payed_for]}) 
      ..... 
     end 
     } 

    p sum 
    sum.round(2) 

end 

感謝。

+0

' "2014から08"' "払っ月" となっていますか?各ファイルまたはすべてのファイルの合計を求めますか? –

+0

例を挙げる場合は、以下を守ってください。1.すべての入力オブジェクトは完全でなければなりません( "..."なし)ので、読者はデータに対してコードを実行できます。 2.質問の本質を保ちながら、可能な限り小さな例を作成します(例:ここでは2つの小さなCSVファイル)。 3 Rubyオブジェクトとして必要な、または期待される結果を表示します。 (オブジェクトが大きければ、その内容を示すだけで十分です。)4.各オブジェクトに変数を割り当てます(例えば、 'arr = [1,2,3]')。そうすれば、読者は答えやコメントでこれらのオブジェクトを定義する必要はありません。ここでは、ファイルイメージを表示しているので、#4を簡単に行うことはできません。 –

+0

あなたは問題があると言います。何が問題なのですか?期待している結果が見えませんか?そうです、代わりに何を見ていますか? –

答えて

2

データがファイルから文字列に読み込まれたとします。

str1 =<<_ 
2014-09-14,2014-08,Panel,84,5839.77 
2014-09-14,2014-08,Brick,118,4251.63 
2014-09-14,2014-09,Brick,97,471.5 
2014-09-14,2014-10,Panel,53,236.22 
2014-09-14,2014-10,Panel,83,4220.77 
_ 
str2 =<<_ 
2014-10-01,2014-08,Brick,34,1522.59 
2014-10-01,2014-09,Brick,117,1285.57 
2014-10-01,2014-09,Brick,136,1925.97 
2014-10-01,2014-10,Brick,24,1032.95 
2014-10-01,2014-11,Brick,113,957.01 
_ 

私たちは、その後、単一の文字列に文字列を結合し、それを行の配列を変換し、私は2番目の値であることが前提とそれぞれ支払わ月の集計値にカウントハッシュを使用することができますフィールド。 newのデフォルト値(ここでは0)に等しい引数が割り当てられている場合は、Hash::newを参照してください。

(str1 + str2).lines.each_with_object(Hash.new(0)) do |line,h| 
    _, payable_month, _, _, amount = line.split(',') 
    h[payable_month] += amount.to_f 
end 
    #=> {"2014-08"=>11613.990000000002, (5839.77 + 4251.63 + 1522.59) 
    # "2014-09"=>3683.04,   (471.5 + 1285.57 + 1925.97) 
    # "2014-10"=>5489.9400000000005, (236.22 + 4220.77 + 1032.95) 
    # "2014-11"=>957.01}    (957.01) 

ハッシュhhがキーpayable_monthを持っていない場合は、等号の右側のh[payable_month]は、デフォルト値を返します

h = Hash.new(0) 

Rubyはh[payable_month] += amount.to_f

h[payable_month] = h[payable_month] + amount.to_f 

にを拡張定義されている場合。我々は代わり

(str1.lines + str2.lines).each_with_object(Hash.new(0))... 

を書かれているか、または我々は、各ファイルのライン・バイ・ラインを読み、一つのファイルにすべてのこれらの行を書かれている可能性があるため、

h[payable_month] = 0 + amount.to_f 
    #=> amount.to_f 

注次を使用する複数のファイル間のすべてのCSVデータを組み合わせること

1

:計算するには、その後に

csv_files = ["01-test.csv", "02-test.csv", "03-test.csv", "04-test.csv", "05-test.csv", "06-test.csv"] 

csv_data = CSV.generate(headers: :first_row) do |csv| 
    csv << CSV.open(csv_files.first).readline 

    csv_files.each do |csv_file| 
    CSV.read(csv_file)[1..-1].each { |row| csv << row } 
    end 
end 

"Payable month"の合計(または"Payment date"払っ月あった明確ではありませんでした) 、次の

  1. RubyのCSVライブラリを使用して、データを解釈します
    data = CSV.parse(csv_data, headers: true) 
    
  2. グループ払っ月別データ

    month_array = data.group_by { |row| row["Payable month"] } 
    # month_array = data.group_by { |row| row["Payment date"][0..6] } 
    

    は、ラインのどちらかを選択し、各monthについて他の

  3. をコメントアウト/すべて"Amount of payment"へのreduceを合計を取得a その月の合計はtotals

    です
    payed_for_each_month = month_array.each_with_object({}) do |(month, rows), totals| 
        totals[month] = rows.reduce(0.0) { |sum, row| sum + row["Amount of payment"].to_f } 
    end 
    

"Payment date"月は合計は、以下を生成する代わりに使用された場合、これは提示されたデータ

payed_for_each_month 
# => {"2014-08"=>21743.98} 

との最終的な結果を生成します。

month_array = data.group_by { |row| row["Payment date"][0..6] } 
# ... 
payed_for_each_month 
# => {"2014-09"=>15019.890000000001, 
#  "2014-10"=>6724.09} 

すべてのコード一緒に:

data = CSV.parse(csv_data, headers: true) 

month_array = data.group_by { |row| row["Payable month"] } 
# month_array = data.group_by { |row| row["Payment date"][0..6] } 

payed_for_each_month = month_array.each_with_object({}) do |(month, rows), totals| 
    totals[month] = rows.reduce(0.0) { |sum, row| sum + row["Amount of payment"].to_f } 
end 

payed_for_each_month 
# => {"2014-08"=>21743.98} 

参考文献:

関連する問題