Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.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_Sorting - Fatal编程技术网

在Python中,当两个文件都未排序时,如何有效地对一个大文件进行排序以匹配另一个大文件中的公共元素?

在Python中,当两个文件都未排序时,如何有效地对一个大文件进行排序以匹配另一个大文件中的公共元素?,python,list,sorting,Python,List,Sorting,我对Python相当陌生,我正在编写一个脚本,它应该包含两个相当大的文本文件(~10MB),并为每个文件创建一个新文件,并记住下面指定的一些规则 文件A的每一行都有制表符分隔的值,文件B的一行包含ID,下一行包含数据。文件B中的ID也存在于文件A中,但并非文件A中的所有ID都存在于文件B中,反之亦然 两个文件都没有字母数字顺序的ID,而且两个文件的顺序不同。我不需要对它们进行字母数字排序,我只需要输出文件的顺序相同,并且只包含具有公共ID的项 以下是文件A的外观: 下面是文件B的外观: 如您

我对Python相当陌生,我正在编写一个脚本,它应该包含两个相当大的文本文件(~10MB),并为每个文件创建一个新文件,并记住下面指定的一些规则

文件A的每一行都有制表符分隔的值,文件B的一行包含ID,下一行包含数据。文件B中的ID也存在于文件A中,但并非文件A中的所有ID都存在于文件B中,反之亦然

两个文件都没有字母数字顺序的ID,而且两个文件的顺序不同。我不需要对它们进行字母数字排序,我只需要输出文件的顺序相同,并且只包含具有公共ID的项

以下是文件A的外观:

下面是文件B的外观:

如您所见,文件A第B列中的项目提供了文件A中可能存在或不存在的标识符

这是我写的一个简单的脚本。对于文件A中的每一行,它将遍历整个文件B,直到找到匹配的ID或到达末尾

该脚本工作正常,但由于它包含一个嵌套循环,它可能在O(n^2)左右(实际上m是O(m*n),m是文件a的大小,n是文件B的大小,但它们通常大小相似),一旦我在实际数据(数百MB或GB单位)上使用它,这可能会成为一个问题

有没有更有效的方法?我怀疑我做这件事的方式不是很像蟒蛇,但我真的一点也不知道它到底出了什么问题。

正如托比亚斯·k所说:

使用csv模块读取第一个文件;对于第二个文件,使用file:dataline=next(file)中的idline,处理idline和dataline,然后将它们放入dict映射id到数据中


你的代码确实不是很有效。相反,我建议使用字典将数据从文件B存储到每个ID。要获取数据,您只需在读取文件的同一迭代器上调用
next
(前提是行数为偶数)。类似于此(未经测试):

然后,当您从文件A读取数据时,您只需在该字典中查找当前ID的数据,而无需反复迭代整个文件B

同样,但不太相关,您可以使用
split(“\t”)
行或使用模块,而不是使用相当复杂的正则表达式从文件a获取ID。 类似于此(也未测试):

您也可以使用
*.
捕获任何剩余字段,而不是枚举所有列:

        num, the_id, *other_stuff_we_do_not_care_about = line.split("\t")

使用
csv
模块读取第一个文件;对于第二个文件,在file:dataline=next(文件)中使用idline的
,使用idline和dataline进行填充,然后将它们放入一个
dict
映射ID到数据中。谢谢!但正如我所说的,我对Python相当陌生,我还不知道如何使用dict。我应该这样做吗
thisdict={“idline”:“HORVU7Hr1G033230.8”,“dataline”:“qmckrlptdtppllkippifsaplvppvlrsdpisrslartgrarrtdppplpsdcvl…”}
No,这样的dict不会帮助您快速找到正确的数据。不要有一个dict列表,每个dict都有一个ID值和一个数据值,而是使用一个dict将所有ID映射到数据,即
{“id1”:“data1”,“id2”:“data2”…}
谢谢,我想我现在对它的理解稍微好一点了。但是在处理文件时如何查找数据?类似于
if-ID\u from\u a in data[line\u ID]:
?@Ludolph314,不,
data[line\u ID]
会在ID不在dict中的情况下引发一个
KeyError
错误。如果ID\u a in data
中的ID\u,你只需执行
即可。我在
ID=line\u ID.strip()处遇到语法错误。[1:];删除新行并“>”^SyntaxError:无效语法
是否与Python 3.7兼容?(错误指向[1:])//EDIT:Nvm,算出了,它是
the_id=line_id.strip()[1:][/code>谢谢,它工作正常,速度惊人!我只有一个问题-在新的文件B中,有一些重复的序列。我怀疑这是因为ID格式-可能有两个不同的序列
HORVU5Hr1G086610.1
HORVU5Hr1G086610.10
,因此检查
如果数据中的_ID
返回更多序列,因为
HORVU5Hr1G086610.1
同时匹配自身和
HORVU5Hr1G086610.10
。你认为有什么办法可以防止这种情况吗?@Ludolph314我不太明白:应该
xxx.1
匹配
xxx.10
,还是不匹配?由于默认情况下它不应该与这些匹配,我想在您的情况下它应该与它们匹配。您可以
rstrip(“0”)
ID来删除任何尾随
0
data = {}
with open("fileb") as fb:
    for line_id in fb:
        the_id = line_id.strip()[1:] # remove newline and ">"
        line_data = next(fb)  # get next line from file
        data[the_id] = line_data.strip()
with open("filea") as fa:
    for line in fa:
        num, the_id, more, stuff, dont, know, what = line.split("\t")
        if the_id in data:
            the_data = data.get(the_id)
            ... to stuff with data ...
        num, the_id, *other_stuff_we_do_not_care_about = line.split("\t")