2011-07-12 1 views
0

私は、CSVファイルに含まれる合計料金と平均料金を計算するためにPythonプログラムを実行しようとしています。なぜ2つのfor文がPythonで一緒に実行されないのですか?

次に、請求書ごとの合計料金と平均料金を計算します。プログラムは合計料金と平均料金を正しく計算しますが、2番目のforステートメントは実行されません。どちらもステートメントを独立して正しく実行します。

import csv 
f = open("transport.csv", "r") 
reader = csv.DictReader(f) 
charges_per_inv = dict() 
inv_reader = csv.DictReader(f) 
inv_dict = dict() 

counter = 0 
inv_counter = 1 

for row in reader: 
    batch_num = row['Batch#'] 
    if batch_num not in charges_per_inv: 
     charges_per_inv [batch_num] = 0.0 
    charges_per_inv [batch_num] += float(row['Amount']) 
    counter = counter + 1       
    #print charges_per_inv #Just a check 

dvalue = [(v) for v in charges_per_inv.values()]  
#print dvalue 
total = sum(dvalue) 
average = float(total)/ counter 
#print counter #Just a check 
print "The total charges is, ", total 
print "The average charge is, ", average 

a = raw_input("Enter Invoice#: ") 

for i in inv_reader: 
    inv_num1 = i["Invoice#"] 
    if inv_num1 == a: 
     if inv_num1 not in inv_dict: 
      inv_dict[inv_num1] = 0.0 
     inv_dict[inv_num1] += float(i['Amount'])  
     inv_counter = inv_counter + 1 
     print inv_dict #Just a check 

inv_amount = [(v) for v in inv_dict.values()] 
#print inv_amount 
inv_total = sum(inv_amount) 
inv_average = float(inv_total)/ inv_counter 
#print inv_counter #Just a check 
print "The total charges is, ", inv_total 
print "The average charge is, ", inv_average 

ここでは、プログラムの出力を示します。

The total charges is, 9069.87 
The average charge is, 72.55896 
Enter Invoice#: 617537 
The total charges is, 0 
The average charge is, 0.0 

答えて

1

これらは、両方とも同じ基本ファイルオブジェクト(f)を使用します。最初のループの後、これは使い果たされました。

reader = csv.DictReader(open("transport.csv")) 
inv_reader = csv.DictReader(open("transport.csv")) 

このようにして、両方のリーダーは独立したファイルオブジェクトを持っています。

3

ファイルはすでにそのポイントで読み込まれているので、2番目のループでは何もしません。最初のループの後でファイルを閉じて再オープンし、その後にinv_readerというインスタンスを移動する必要があります。

さらに、ループを1つにマージしておく方が効率的です。

+0

ありがとうございます!これは機能します。 – amp28

+2

もう1つの解決策は、最初のループの後に 'f.seek(0)'をすることです。 – Evpok

+0

@Evpok:ヘッダー行をスキップするには 'f.readline()'する必要があるか、まだ初期化された 'DictReader'によってレコードとして扱われると思います。 –

0

同じファイルオブジェクト(繰り返し可能なもの)を使用してcsvリーダー(iterable)に作成しました。最初のcsvリーダー(reader)から行を消費する場合は、ファイルの行(f)を消費します。 2番目のcsvリーダー(inv_reader)を繰り返し実行すると、ファイルオブジェクト(f)の行が使用されました。反復することは何も残っていません。

2

最初のループに水がいっぱいのガラスを手渡し、それを飲んだ後、空のガラスを次のループに手渡すようなものです。

0

ここで参考までに、コードをかなり修正する方法を説明します。これは実際の機能に変更はありません。 transport.csvにたくさんのエントリがある場合は、より小さく、効率的にになることに注意してください。それが問題であることが分かっていた場合は、DictReaderをすぐにタプルに変換する代わりに、それを再作成します(len(items)の処理方法の変更を含み、DictReaderDictReaderを再初期化します。良い提案、Evpok !。)と、ヘッダー行を取り除くためにf.readline()

import csv 
from collections import defaultdict 

with open('transport.csv', 'rb') as f: 
    items = tuple(csv.DictReader(f)) 

charges_per_inv = defaultdict(float) 
for row in items: 
    charges_per_inv[row['Batch#']] += float(row['Amount']) 

total = sum(charges_per_inv.values()) 
print 'The total charges is, ', total 
print 'The average charge is, ', total/len(items) 

a = raw_input('Enter Invoice#: ') 

invoice_amount = 0.0 
invoice_items = 0 
for row in items: 
    invoice_num = row['Invoice#'] 
    if invoice_num == a: 
     invoice_amount += float(row['Amount']) 
     invoice_items += 1 

print 'The total charges is, ', invoice_amount 
print 'The average charge is, ', invoice_amount/invoice_items 

私が言及した効率の問題も開始時に請求書番号を取得し、これだけのCSVファイルにアクセスする必要がある一つのループを持つことによって除去することができます。

import csv 
from collections import defaultdict 

a = raw_input('Enter Invoice#: ') 

with open('transport.csv', 'rb') as f: 
    reader = csv.DictReader(f) 

    num_items = 0 
    charges_per_inv = defaultdict(float) 
    invoice_amount = 0.0 
    invoice_items = 0 

    for row in reader: 
     charges_per_inv[row['Batch#']] += float(row['Amount']) 
     invoice_num = row['Invoice#'] 
     if invoice_num == a: 
      invoice_amount += float(row['Amount']) 
      invoice_items += 1 
     num_items += 1 

    total = sum(charges_per_inv.values()) 
    print 'The total charges is, ', total 
    print 'The average charge is, ', total/num_items 

    print 'The total invoice item charges is, ', invoice_amount 
    print 'The average invoice item charge is, ', invoice_amount/invoice_items 

私が行ったことについて質問がある場合は、お尋ねください。

+0

これは本当に効率的です。私はPythonとプログラミングには新しいです。これにより、ファイルを効率的に開いて読み込む方法についての答えが得られました。 – amp28

+0

@ amp28:それがあなたを助けてくれることを願っています。なぜ私が何をしたのか知りたいのであれば、質問してください。私は説明したいと思っています。 –

関連する問題