10

我正在尝试比较两个 csv 文件(fileA 和 fileB),并从 fileA 中删除在 fileB 中找不到的所有行。我希望能够在不创建第三个文件的情况下做到这一点。我以为我可以使用 csv writer 模块来做到这一点,但现在我在猜测自己。

目前,我正在使用以下代码记录文件 B 中的比较数据:

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)
4

3 回答 3

8

此解决方案使用fileinputwith inplace=True,它写入一个临时文件,然后在末尾自动将其重命名为您的文件名。您不能从文件中删除行,但可以只用您想要的行重写它。

如果将关键字参数inplace=1传递给构造函数fileinput.input()或将其传递给FileInput构造函数,则将文件移动到备份文件并将标准输出定向到输入文件(如果与备份文件同名的文件已经存在,它将被静默替换) . 这使得编写一个过滤器来重写其输入文件成为可能。

文件A

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

文件B

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)

文件A

h1,h2,h3
a,b,c    
g,h,i
于 2013-04-29T05:04:03.657 回答
3

CSV 不是数据库格式。它作为一个整体被读取和写入。您不能删除中间的行。因此,在不创建第三个文件的情况下执行此操作的唯一方法是在内存中完全读入文件,然后将其写出,而不会出现违规行。

但总的来说,最好使用第三个文件。

于 2013-04-29T04:51:35.817 回答
3

正如 Lennart 所述,您无法在迭代 CSV 文件时就地修改它。

如果您真的反对创建第三个文件,您可能需要考虑使用带有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())
于 2013-04-29T04:53:11.733 回答