2013-04-29 19 views
8

私は2つのcsvファイル(fileAとfileB)を比較しようとしていますが、fileBに見つからないfileAの行はすべて削除します。私は3番目のファイルを作成せずにこれを行うことができるようにしたい。私はCSVライターモジュールを使ってこれを行うことができると思ったが、今は自分自身を推測している。Pythonで行を削除するには

removal_list = set() 
with open('fileB', 'rb') as file_b: 
    reader1 = csv.reader(file_b) 
    next(reader1) 
    for row in reader1: 
     removal_list.add((row[0], row[2])) 

私がこだわっていると行を削除する方法がわからない場所です::

with open('fileA', 'ab') as file_a: 
    with open('fileB', 'rb') as file_b: 
     writer = csv.writer(file_a) 
      reader2 = csv.reader(file_b) 
      next(reader2) 
      for row in reader2: 
       if (row[0], row[2]) not in removal_list: 
       # If row was not present in file B, Delete it from file A. 
       #stuck here: writer.<HowDoIRemoveRow>(row) 
現在、私は、ファイルBからの私の比較データを記録するために、次のコードを使用してい

+1

['sqlite'](http://docs.python.org/2/library/sqlite3.html)は、フラットファイルベースのデータベースで、そのドライバは現代版のPythonに含まれています。あなたがしようとしていることを考えれば、より良い選択肢かもしれません。 –

+0

愚かな質問を申し訳ありませんが、これはファイルBの正確なコピーを作成するでしょうか? –

答えて

7

このソリューションは、一時ファイルに書き込みinplace=Truefileinput、使用した後、自動的にあなたのファイルへの最後でそれをリネーム名。 ファイルから行を削除することはできませんが、必要なものだけで書き直すことはできます。

キーワード引数inplace=1fileinput.input()またはFileInputコンストラクタに渡された場合、ファイルがバックアップファイルに移動され、標準出力が入力ファイルに向けられている(バックアップファイルと同じ名前のファイルであれば既に存在する場合、それは静かに置き換えられる)。これにより、入力ファイルを正しい位置に書き換えるフィルタを作成することができます。

FILEA

h1,h2,h3 
a,b,c 
d,e,f 
g,h,i 
j,k,l 

FILEB

h1,h2,h3 
a,b,c 
1,2,3 
g,h,i 
4,5,6 

import fileinput, sys, csv 

with open('fileB', 'rb') as file_b: 
    r = csv.reader(file_b) 
    next(r) #skip header 
    seen = {(row[0], row[2]) for row in r} 

f = fileinput.input('fileA', inplace=True) # sys.stdout is redirected to the file 
print next(f), # write header as first line 

w = csv.writer(sys.stdout) 
for row in csv.reader(f): 
    if (row[0], row[2]) in seen: # write it if it's in B 
     w.writerow(row) 

FILEA

h1,h2,h3 
a,b,c  
g,h,i 
+0

説明では扱われていない微妙な改善点:このコードでは、「このデータはありますか?」という回答には、はるかに最適なデータ構造のセットが使用されています。リスト(これは毎回反復されなければならない)よりも優れています。 –

+0

@David Opも – jamylak

+0

D'ohですが、セットを使用しました。 S /彼ははっきり言った。さて、ちょっとしたアドバイス - それを削除 "リスト"と呼んでいないか、私のような骨頭の人が変数のタイプについて混乱してしまいます。 =) –

3

CSVはデータベース形式ではありません。それは全体として読み書きされます。途中の行を削除することはできません。したがって、3番目のファイルを作成せずにこれを実行する唯一の方法は、メモリ内のファイルを完全に読み込んだ後、不快な行なしに書き出すことです。

一般に、3番目のファイルを使用する方がよいでしょう。

3

Lennartが説明したように、CSVファイルを反復処理するときに、その場でCSVファイルを変更することはできません。

3番目のファイルを作成することに本当に反対の場合は、StringIOという文字列バッファを使用して、ファイルAの新しい内容をメモリに構築することを検討してください。スクリプトの終わりには、ファイルAの上にバッファの内容を書き込むことができ

from cStringIO import StringIO 


with open('fileB', 'rb') as file_b: 
    new_a_buf = StringIO() 
    writer = csv.writer(new_a_buf) 
    reader2 = csv.reader(file_b) 
    next(reader2) 
    for row in reader2: 
     if (row[0], row[2]) not in removal_list: 
      writer.writerow(row) 

# At this point, the contents (new_a_buf) exist in memory 
with open('fileA', 'wb') as file_a: 
    file_a.write(new_a_buf.getvalue()) 
+0

ここでは注意が必要なことです。入力ファイルが大きい場合は、使用可能なメモリが使い果たされる可能性があります。 –

+0

あなたは別のファイルに書き込んで、最後に名前を変更することもできます。それは私の解決策です。 – jamylak

+0

@jamylak、私はあなたに完全に同意します。そして、それはまさに私がこの状況でやることです。私はちょうどこれが技術的に尋ねる者が探しているものを満たすことに役立つだろうと考えました。 –

関連する問題