我正在处理一个大型csv文件,其中包含歌曲及其所有者属性。每个歌曲记录都是自上而下编写的,每个标题下方都有相关的作者和发行者名称。因此,一首给定的歌曲可能包含4至6行,具体取决于控制该歌曲的作者/发行商的数量(例如下面的标题行):
Title,RoleType,Name,Shares,Note
BOOGIE BREAK 2,ASCAP,Total Current ASCAP Share,100,
BOOGIE BREAK 2,W,MERCADO JOSEPH M,,
BOOGIE BREAK 2,P,CRAFTIN MUSIC,,
BOOGIE BREAK 2,P,NEXT DIMENSION MUSIC,,
我目前正试图遍历整个文件,以提取所有包含前导空格的歌曲标题(例如“歌曲标题”)。这是我当前正在使用的代码:
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
,但是根据我使用的数量,它要么根本不影响语句,要么中断得太快,没有捕获任何行。>
我还尝试将其包装在函数中并实现return
,但是由于某种原因,该代码似乎只在第一行进行迭代(不包括标题行,我会跳过)。
非常感谢您的时间,
答案 0 :(得分:0)
您可以使用词典查找每首歌曲并将其所有关联值分组:
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
答案 1 :(得分:0)
list(ascap)
并不是在帮您忙。 reader
对象是其内容的迭代器,但是直到需要ti时,它们才将其全部加载到内存中。只需直接迭代reader
对象即可。
对于每一行,只需检查row[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
即可跳过文件的其余部分。
答案 2 :(得分:0)
以下是您可以改进的一些内容:
直接使用reader
对象作为迭代器,而无需创建中间列表。这样可以节省您的计算时间和内存。
仅检查一行(标题)中的第一个值,而不是全部。
删除不必要的else
子句。
结合所有这些并应用一些最佳实践,您可以做到:
import csv
import re
with open('data/ascap_catalog1.csv') as ac, open('output/sws.txt', 'w') as sws:
reader = csv.reader(ac)
for row in reader:
if re.search(r'\A\s+', row[0]):
print(row, file=sws)
似乎带有前导空格的歌曲标题都聚集在 文件的开头。
在这种情况下,只要标题带有前导空格,您就可以使用itertools.takewhile
来迭代文件:
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)
答案 3 :(得分:0)
这个对我来说效果很好,似乎很简单。
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')