如何从CSV文件中提取目标行、前面的行和后面的行?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (339)

我一直试图弄清楚如何通过for循环和enumerate我在python中给出的对象来实现这一点。我有时间的格式HH:MM。我有一个csv文件,其中第一列是以相同格式后面的时间戳。然后我在文件中搜索匹配的时间,然后我提取该行以便以后转换为XML文件。但是,我需要提取该行之前的行以及该目标行之后的行。我尝试过以下代码:

def findRow(timeID, filename):
    rows = []
    csvFile = csv.reader(open(filename, "rb"), delimiter=",")
    for i, row in enumerate(csvFile):
        if timeID == timeInRow:
            rows.append(i-1)
            rows.append(i)
            rows.append(i+1)
            return rows

但是,我很快意识到这不是正确的方法,因为我正在提取索引而不是值。我需要的是像行[i-1],行[i],行[i + 1]。换句话说,我需要i匹配行的元素。

是否有捷径可寻?我已经考虑过使用range(csvFile),但我老实说不知道最终会做什么。

提问于
用户回答回答于

对上述方法的替代(功能)方法是使用zip或改变它。就像是:

rows = list(csv.reader(f))
for x, y, z in zip(rows, rows[1:], rows[2:]):
    # y is the middle row, x is above it, and z below it
    pass

如果你想在迭代中包含前两行和最后两行

(None, None, rows[0])
(None, rows[0], rows[1])
(rows[-2], rows[-1], None)
(rows[-1], None, None)

不是说这肯定比其他答案更好,但它是我考虑写的另一种方法。

使用itertools.islice:

rows = list(csv.reader(f))
from itertools import islice
for x, y, z in zip(rows, islice(rows, 1, None), islice(rows, 2, None)):
    # y is the middle row, x is above it, and z below it
    pass
用户回答回答于

我会用另一种方法:

  • 将前一行存储在循环中
  • 如果匹配,则使用next获取下一行,并返回3行

像这样:

prev_row = []  # just in case it matches at first row
for row in csvFile:
    # something must be done to extract timeInRow from row here!
    if timeID == timeInRow:
        return [prev_row,row,next(csvFile,[])]
    prev_row = row  # save current row for next iteration

这种线性方法有效,但如果行按时间排序并且你需要执行多次搜索,则更好的方法(更快)可能会创建行列表,时间列表,然后使用bisect模块计算插入点时间列表,检查时间是否匹配,并使用索引返回行列表的切片。

就像是:

list_of_rows = list(csvFile)
list_of_times = [x[3] for x in list_of_rows] # assume that the time is the 4th column here
i = bisect.bisect(list_of_rows,timeInRow)
if list_of_rows[i] == timeInRow:
    return list_of_rows[max(i-1,0):min(i+2,len(list_of_rows)]

扫码关注云+社区

领取腾讯云代金券