Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,将列表项与大文件中的行匹配的最有效方法是什么?_Python_List_Match - Fatal编程技术网

在Python中,将列表项与大文件中的行匹配的最有效方法是什么?

在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

我有一个大文件(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 = 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:您是对的,但是作者示例有三列,元组解包应该比通过索引访问快一点。