在python中迭代CSV文件以查找带有前导空格的标题

在python中迭代CSV文件以查找带有前导空格的标题,python,python-3.x,csv,Python,Python 3.x,Csv,我正在使用一个包含歌曲及其所有者属性的大型csv文件。每个歌曲记录都是自上而下写的,每个标题下都有相关的作者和出版商的名字。因此,一首给定的歌曲可能由4-6行组成,这取决于有多少作者/出版商控制它(下面是标题行的示例): 我目前正在尝试循环遍历整个文件,以提取包含前导空格的所有歌曲标题(例如,“song title”)。以下是我当前使用的代码: import csv import re with open('output/sws.txt', 'w') as sws: with open

我正在使用一个包含歌曲及其所有者属性的大型csv文件。每个歌曲记录都是自上而下写的,每个标题下都有相关的作者和出版商的名字。因此,一首给定的歌曲可能由4-6行组成,这取决于有多少作者/出版商控制它(下面是标题行的示例):

我目前正在尝试循环遍历整个文件,以提取包含前导空格的所有歌曲标题(例如,“song title”)。以下是我当前使用的代码:

import csv
import re

with open('output/sws.txt', 'w') as sws:
    with open('data/ascap_catalog1.csv', 'r') as ac:
        ascap = csv.reader(ac, delimiter=',')
        ascap = list(ascap)
        for row in ascap:
            for strings in row:
                if re.search('\A\s+', strings):
                    row = str(row)
                    sws.write(row) 
                    sws.write('\n')
                else:
                    continue
由于我正在处理的这个csv文件的大小(~2GB),遍历并生成结果文件需要相当长的时间。然而,根据我得到的结果,似乎带前导空格的歌曲标题都聚集在文件的开头。这些歌曲全部列出后,将显示不带前导空格的普通歌曲

有没有办法让这段代码在时间上更有效率?我尝试在每个for和if语句之后使用一些
break
s,但根据使用的数量,它要么根本不会影响语句,要么中断得太快,无法捕获任何行

我还尝试将其包装在函数中并实现
return
,但是,出于某种原因,代码似乎只遍历第一行(不包括标题行,我将跳过它)


非常感谢您的时间,

您可以使用字典查找每首歌曲并将其所有相关值分组:

from collections import defaultdict
import csv, re
d = defaultdict(list)
count = 0 #count needed to remove the header, without loading the full data into memory
with open('filename.csv') as f:
  for a, *b in csv.reader(f):
    if count:
      if re.findall('^\s', a):
        d[a].append(b)
    count += 1
list(ascap)
对你没有任何好处
reader
对象是其内容的迭代器,但在需要时才将其全部加载到内存中。直接迭代
读取器
对象即可

对于每一行,只需选中
行[0][0].isspace()
。这将检查第一个条目的第一个字符,这是确定某个内容是否以空格开头所需的全部内容

with open('output/sws.txt', 'w', newline="") as sws:
    with open('data/ascap_catalog1.csv', 'r', newline="") as ac:
        ascap = csv.reader(ac, delimiter=',')
        for row in ascap:
            if row and row[0] and row[0][0].isspace():
                print(row, file=sws)

您还可以处理输出,比如在最后写入行之前将要保留在列表中的所有行保存起来。如果所有前导的空白名称都排在第一位,听起来您的输入可能会被排序。如果是这种情况,您可以添加
else:break
跳过文件的其余部分。

以下是一些您可以改进的地方:

  • 直接将对象用作迭代器,而不创建中间列表。这将节省您的计算时间和内存

  • 仅检查行中的第一个值(即标题),而不是全部

  • 删除不必要的
    else
    子句

结合所有这些并应用一些最佳实践,您可以做到:

带前导空格的歌曲标题似乎都聚集在一起 文件的开头

在这种情况下,只要标题有前导空格,就可以使用来迭代文件:

import csv
import re
from itertools import takewhile

with open('data/ascap_catalog1.csv') as ac, open('output/sws.txt', 'w') as sws:
    reader = csv.reader(ac)
    next(reader)  # skip the header
    for row in takewhile(lambda x: re.search(r'\A\s+', x[0]), reader):
        print(row, file=sws)

这个对我来说很好,看起来很简单

import csv
import re

with open('C:\\results.csv', 'w') as sws:
    with open('C:\\ascap.csv', 'r') as ac:
        ascap = csv.reader(ac, delimiter=',')
        for row in ascap:
            if re.match('\s+', row[0]):
                sws.write(str(row)+ '\n')

这并不能特别回答您的问题,但一般来说,使用
pandas
这样的库进行.csv处理会提高处理速度。也许您可以尝试先列出处理过的歌曲,然后在最后立即编写。不进行很多小的读写操作。@Jean-Françoisfare这是可能的,尽管我使用了
append
来保留与每个歌曲发行者相关的值,这些值可能包含也可能不包含不同的数据值,例如角色类型、名称、共享等。
import csv
import re
from itertools import takewhile

with open('data/ascap_catalog1.csv') as ac, open('output/sws.txt', 'w') as sws:
    reader = csv.reader(ac)
    next(reader)  # skip the header
    for row in takewhile(lambda x: re.search(r'\A\s+', x[0]), reader):
        print(row, file=sws)
import csv
import re

with open('C:\\results.csv', 'w') as sws:
    with open('C:\\ascap.csv', 'r') as ac:
        ascap = csv.reader(ac, delimiter=',')
        for row in ascap:
            if re.match('\s+', row[0]):
                sws.write(str(row)+ '\n')