【问题标题】:Skip the last row of CSV file when iterating in Python在 Python 中迭代时跳过 CSV 文件的最后一行
【发布时间】:2013-06-01 00:29:05
【问题描述】:

我正在使用从数据仓库 (Cognos) 获得的 CSV 文件进行数据分析。 CSV 文件的最后一行总结了上述所有行,但我不需要此行进行分析,因此我想跳过最后一行。

我正在考虑添加“if”语句来检查我的“for”循环中的列名,如下所示。

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 文件时,是否有任何 Pythonian 方式可以跳过最后一行?

【问题讨论】:

  • 如果你在 ninx 上,你可以使用head -n -1 yourfile.csv 来回显文件而不用最后一行
  • 你的意思是 unix-lke 操作系统吗?不幸的是,我正在使用我的公司 PC。不过谢谢你,当我在家里弄脏手时它会派上用场的。

标签: python csv


【解决方案1】:

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

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)

【讨论】:

  • Martijn,您的帐户背后似乎有一个 python 开发团队 :) 生成快速准确的答案看起来真是太棒了!
  • 谢谢Martijin。那速度快得惊人。代码也像魅力一样工作。除了 "prev = next(iterator):" 末尾的 ":" 必须删除。
  • 好了!非常感谢。
  • 这正是我想要的。一般来说,当你想“向前看”时,通常更容易将问题改为“向后看”。
【解决方案2】:

一个广义的“skip-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 循环。
  • @MartijnPieters,说得好。出于可读性的原因,我倾向于保留 for 循环。您的评论应该能够将每个人指向更有效的islice 选项!
  • 如果您有兴趣,它是consume recipe in the itertools documentation 的一部分。
猜你喜欢
  • 2015-01-20
  • 2013-02-19
  • 1970-01-01
  • 2021-12-24
  • 2018-05-24
  • 1970-01-01
  • 1970-01-01
  • 2020-03-29
  • 2016-10-04
相关资源
最近更新 更多