在Python中迭代CSV文件时跳过最后一行

6

我正在使用从数据仓库(Cognos)获取的CSV文件进行数据分析。该CSV文件有一个汇总所有上方行的最后一行,但是我不需要这一行进行分析,所以我想跳过最后一行。

我考虑在我的“for”循环中添加一个“if”语句,检查列名是否符合条件,如以下代码所示。

import CSV

with open('COGNOS.csv', "rb") as f, open('New_COGNOS.csv', "wb") as w:
    #Open 2 CSV files. One to read and the other to save.
    CSV_raw = csv.reader(f)
    CSV_new = csv.writer(w)
    for row in CSV_raw:
        item_num = row[3].split(" ")[0]
        row.append(item_num)
        if row[0] == "All Materials (By Collection)": break
        CSV_new.writerow(row)

然而,这样做似乎会浪费很多资源。在迭代CSV文件时是否有任何可以跳过最后一行的Python方法?


如果你在使用Nginx,你可以使用head -n -1 yourfile.csv命令来输出文件除了最后一行的内容。 - dm03514
你是指类Unix操作系统吗?不幸的是,我正在使用公司电脑。谢谢你的建议,当我在家里动手时,这会很有用。 - Yong Jun Kim
2个回答

18

你可以编写一个生成器,它会返回输入迭代器中除了最后一个条目以外的所有内容:

def skip_last(iterator):
    prev = next(iterator)
    for item in iterator:
        yield prev
        prev = item

然后将您的CSV_raw读取器对象包装在其中:

for row in skip_last(CSV_raw):

生成器基本上会获取第一个条目,然后开始循环,并在每次迭代时产生先前的条目。当输入迭代器完成时,仍会有一行未返回。

让您跳过最后n个元素的通用版本如下:

from collections import deque
from itertools import islice

def skip_last_n(iterator, n=1):
    it = iter(iterator)
    prev = deque(islice(it, n), n)
    for item in it:
        yield prev.popleft()
        prev.append(item)

2
Martijn,看起来你的账户背后有一支Python开发团队 :) 能够快速准确地回答问题真是太棒了! - alecxe
谢谢Martijin。这太快了。代码也像魔法一样运行良好。只是“prev = next(iterator):”末尾的“:”必须删除。 - Yong Jun Kim
好的!非常感谢。 - Yong Jun Kim
这正是我想要做的。通常,当你想要“向前看”时,更容易将问题改为“向后看”。 - kindall

1
一个通用的“跳过n个”的生成器。
from __future__ import print_function
from StringIO import StringIO
from itertools import tee
s = '''\
1
2
3
4
5
6
7
8
'''
def skip_last_n(iterator, n=1):
    a, b = tee(iterator)
    for x in xrange(n):
            next(a)
    for line in a:
            yield next(b)

i = StringIO(s)
for x in skip_last_n(i, 1):
    print(x, end='')
1
2
3
4
5
6
7

i = StringIO(s)
for x in skip_last_n(i, 3):
    print(x, end='')
1
2
3
4
5

使用tee作为n大小的缓冲区也是一个不错的想法。使用itertools.islice()快速跳过n个项目,而不是使用for x in xrange(n)循环:next(islice(a, n, n), None)在C代码中消耗了n个项目,这将随时击败for循环。 - Martijn Pieters
@MartijnPieters,说得好。出于可读性的原因,我倾向于保留for循环。您的评论应该能够指向更有效的islice选项! - iruvar
如果您感兴趣,这是itertools文档中consume配方的一部分。 - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接