在Python中,将列表项与大文件中的行匹配的最有效方法是什么?
我有一个大文件(5Gb),名为在Python中,将列表项与大文件中的行匹配的最有效方法是什么?,python,list,match,Python,List,Match,我有一个大文件(5Gb),名为my_file。我有一个名为my_list的列表。读取文件中每一行的最有效方法是什么?如果my_list中的项目与my_file中的项目匹配,请创建一个名为matches的新列表,其中包含my_file中的行中的项目以及发生匹配的my_list中的项目。以下是我试图做的: def calc(my_file, my_list) matches = [] my_file.seek(0,0) for i in my_file: i
my_file
。我有一个名为my_list
的列表。读取文件中每一行的最有效方法是什么?如果my_list
中的项目与my_file
中的项目匹配,请创建一个名为matches
的新列表,其中包含my_file
中的行中的项目以及发生匹配的my_list
中的项目。以下是我试图做的:
def calc(my_file, my_list)
matches = []
my_file.seek(0,0)
for i in my_file:
i = list(i.rstrip('\n').split('\t'))
for v in my_list:
if v[1] == i[2]:
item = v[0], i[1], i[3]
matches.append(item)
return matches
以下是我的文件中的一些行:
lion 4 blue ch3
sheep 1 red pq2
frog 9 green xd7
donkey 2 aqua zr8
以下是我的列表中的一些项目
intel yellow
amd green
msi aqua
在上述示例中,所需的输出(列表列表列表)为:
[['amd', 9, 'xd7'], ['msi', 2, 'zr8']]
我的代码目前正在运行,尽管速度非常慢。使用生成器或序列化会有帮助吗?谢谢 将项目保存在词汇表而不是列表中(我们称之为
items
)。现在,在执行此操作的同时遍历文件,并选择要查找的键(i[2]
),然后检查它是否在项中
项目将是
dict (yellow = "intel", green = "amd", aqua = "msi")
if i[2] in items:
yield [[items[i[2]], i[1], i[3]]
所以检查部分应该是
dict (yellow = "intel", green = "amd", aqua = "msi")
if i[2] in items:
yield [[items[i[2]], i[1], i[3]]
由于您只是创建列表并返回它,因此使用生成器可能有助于存储程序的特征,而不是将整个内容放入列表并返回它 你可以建立一个用于查找v的口述记录。我添加了进一步的小优化:
def calc(my_file, my_list)
vd = dict( (v[1],v[0]) for v in my_list)
my_file.seek(0,0)
for line in my_file:
f0, f1, f2, f3 = line[:-1].split('\t')
v0 = vd.get(f2)
if v0 is not None:
yield (v0, f1, f3)
对于较大的我的\u列表
,这应该快得多
使用get
比检查i[2]
是否在vd
+访问vd[i[2]]
为了在这些优化之外获得更高的速度,我建议读入文件的开销并不是很大,但是根据您的示例代码,您可以通过将列表存储为dict(目标字段作为键)来加速匹配
下面是一个示例,其中有一些额外的优化调整:
mylist = {
"yellow" : "intel",
"green" : "amd",
# ....
}
matches = []
for line in my_file:
i = line[:-1].split("\t")
try: # faster to ask for forgiveness than permission
matches.append([mylist[i[2]], i[1], i[3]])
except NameError:
pass
但请再次注意,您的大多数性能瓶颈将出现在文件的读取中,并且此级别的优化可能不会对运行时产生足够大的影响。以下是有关使用模块的一个变体:
例如:
def test():
my_file = """\
lion 4 blue ch3
sheep 1 red pq2
frog 9 green xd7
donkey 2 aqua zr8
""".splitlines()
my_list = [
("intel", "yellow"),
("amd", "green"),
("msi", "aqua"),
]
res = list(calc_csv(my_file, my_list))
assert [('amd', '9', 'xd7'), ('msi', '2', 'zr8')] == res
if __name__=="__main__":
test()
“真的很慢”?请张贴2件东西。运行所需的实际时间以及打开(“我的文件”、“r”)所需的时间。read()
@S.Lott:在这种情况下,I/O可以占主导地位;虽然这个文件是5G,所以对于“打开中的”(“我的文件”):pass在这里可能更合适。@J.F.塞巴斯蒂安:说得好。但是,如果没有数字,这可能只是一个标准的过早优化案例。根据我目前的代码,程序大约需要2天才能完成。我在my_file
的一个版本上运行了这些数字,该版本的大小约为1/100,运行程序的时间约为1小时,打开文件的时间不到一分钟。使用.get()
很有好处。我注意到了这一点,并相应地更新了我的答案,但由于您明确提到了它,因此+1。顺便说一句,.split()
返回一个列表,因此无需对其调用list()
。f1,f2,f3=line[:-1]。如果要解包的项目数不匹配,split()
将引发ValueError
异常。@Shawn:ok,我从原稿上粘贴了它,并修复了它now@Shawn:您是对的,但是作者示例有三列,元组解包应该比通过索引访问快一点。