编辑
在您在下面发表评论后,我认为这就是您想要做的。我已将原始帖子留在下面,以防万一其中的任何内容对您有用。
所以,我认为你想做以下事情。首先,此代码会将 file1 中的每个单独的同义词读入 a set
- 这是一个有用的结构,因为它会自动删除所有重复项,并且查找速度非常快。它就像一本字典,但只有键,没有值。如果您不想删除重复项,我们需要稍作更改。
file1_data = set()
with open("file1.txt", "r") as fd:
for line in fd:
file1_data.update(i.strip() for i in line.split("///") if i.strip())
然后你想通过 file2 寻找匹配:
with open("file2.txt", "r") as in_fd:
with open("output.txt", "w") as out_fd:
for line in in_fd:
items = line.split("\t")
if len(items) < 5:
# This is so we don't crash if we find a line that's too short
continue
synonyms = set(i.strip() for i in items[4].split("|"))
overlap = synonyms & file1_data
if overlap:
# Build string of columns from file2, stripping out 5th column.
output_str = "\t".join(items[:4] + items[5:])
for item in overlap:
out_fd.write("\t".join((item, output_str)))
所以它的作用是打开 file2 和一个输出文件。它遍历 file2 中的每一行,并首先检查它是否有足够的列以至少有第 5 列 - 如果没有,它会忽略该行(您可能想要打印错误)。
然后它将第 5 列拆分|
并从该列表中构建一个set
(称为synonyms
)。这set
很有用,因为我们可以非常快速地找到this 与 file1 中所有同义词的前一组的交集- 这个交集存储在overlap
.
然后我们要做的是检查是否有任何重叠 - 如果没有,我们忽略这一行,因为在 file1 中找不到同义词。这个检查主要是为了速度,所以如果我们不打算将它用于这一行,我们就不会费心构建输出字符串。
如果有重叠,我们构建一个字符串,它是我们要附加到同义词的完整列列表 - 即使有多个匹配项,我们也可以将其构建为一个字符串一次,因为每个匹配项都是相同的,因为它all 来自 file2 中的行。这比每次都将其构建为字符串要快。
然后,对于在 file1 中匹配的每个同义词,我们将一行作为同义词写入输出,然后是一个制表符,然后是 file2 中该行的其余部分。因为我们按标签拆分,所以我们必须将它们放回"\t".join(...)
. 这是假设我是正确的,您想删除第 5 列 - 如果您不想删除它,那么它会更容易,因为您可以使用 file2 中的行,最后去掉换行符。
希望这更接近您的需求?
原帖
您没有给出文件大小的任何指示,但我将假设它们足够小以适合内存 - 如果没有,您的问题会变得有点棘手。
因此,第一步可能是打开文件#2 并读入数据。你可以用这样的代码来做到这一点:
file2_data = {}
with open("file2.txt", "r") as fd:
for line in fd:
items = line.split("\t")
file2_data[frozenset(i.strip() for i in items[0].split("|"))] = items[1:]
这将创建file2_data
一个字典,将一个单词映射到该行上剩余项目的列表。正如我在之前的评论中提到的,您还应该考虑单词是否可以重复以及您希望如何处理。
在此之后,您可以读取第一个文件并将数据附加到该文件中的每个单词:
with open("file1.txt", "r") as fd:
with open("output.txt", "w") as fd_out:
for line in fd:
words = set(i.strip() for i in line.split("///"))
for file2_words, file2_cols in file2_data.iteritems():
overlap = file2_words & words
if overlap:
fd_out.write("///".join(overlap) + "\t" + "\t".join(file2_cols))
您最终应该得到的是每一行,output.txt
其中两个文件中的单词列表至少有一个共同的单词,第一项是共同的单词,由///
. 该输出文件中的其他列将是文件#2 中匹配行的其他列。
如果这不是你想要的,你需要更具体一点。
顺便说一句,可能有比我上面概述的 O(N^2) 方法更有效的方法(即它在一个整个文件中运行的次数与另一个文件中的行数一样多),但这需要更详细有关如何匹配线条的信息。
例如,您可以构建一个字典,将一个单词映射到该单词出现的行列表 - 这使得检查匹配行比上面执行的完整扫描快得多。但是,由于您似乎想要行之间的重叠,这显得有些繁琐,因此我认为上面概述的简单方法就足够了,无需更多细节。