【问题标题】:Test if the lines in file1 are a subset of the lines in file2测试 file1 中的行是否是 file2 中的行的子集
【发布时间】:2017-08-25 16:19:48
【问题描述】:

我曾尝试在网上搜索答案,但不幸的是没有成功。所以我在这里问:

我想弄清楚file1 中的所有行是否都存在于file2 中。幸运的是,我可以只比较整行而不是单个单词等。不幸的是,我正在处理 GB 文件,所以我尝试过的一些基本解决方案给了我记忆错误。

目前我有以下代码不起作用。一些指导将不胜感激。

# Checks if all lines in file1 are present in file2
def isFile1SubsetOfFile2(file1 , file2):
    file1 = open(file1, "r")


    for line1 in file1:        
        with open(file2, "r+b") as f:

            mm=mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 
            my_str_as_bytes = str.encode(line1)
            result = mm.find(line1.strip().encode())
            print(result)
            if result == -1:
                return False
    return True

示例文件2:

This is line1.
This is line2.
This is line3.
This is line4.
This is line5.
This is line6.
This is line7.
This is line8.
This is line9.

应该通过,例如文件 1 是:

This is line4.
This is line5.

应该失败,例如文件 1 是:

This is line4.
This is line10.

编辑:我刚刚添加了我的代码的工作版本以供其他人受益。没有内存错误,但速度很慢。

【问题讨论】:

  • Ick,你的代码是O(m*n)。在O(m log m + n log n) 中执行此操作很简单,有时可以在O(m + n) 中执行此操作
  • 你所说的关于算法复杂性等的内容超出了我的理解范围。
  • 那么在你学习任何其他关于编程的知识之前,先了解一下算法复杂性和大O符号。这是重要的
  • 你能给我指点一些关于这个的外行文章吗?谢谢
  • 维基百科很不错:en.wikipedia.org/wiki/Big_O_notationen.wikipedia.org/wiki/Analysis_of_algorithms - 但任何像样的教科书也应该涵盖它

标签: python python-3.x filecompare


【解决方案1】:

我不确定为什么它不起作用,但我想我知道如何解决它:

def is_subset_of(file1, file2):
    with open(file1, 'r') as f1, open(file2, 'r') as f2:
        for line in f1:
            line = line.strip()
            f2.seek(0)   # go to the start of f2
            if line not in (line2.strip() for line2 in f2):
                return False
    return True

这避免了多次打开第二个文件,因为它总是为每一行重新开始,并且在任何时候你只在内存中保存 2 行。这应该是对内存非常友好的。

另一种方法(可能更快)是对file1file2 进行排序。这样,如果字符串在词法上小于第一个文件中的字符串,则可以逐行比较并移至另一个文件中的下一行。而不是可以在O(n*log(n)) 中执行的O(n**2)。但是,这要复杂得多,我不知道对 GB 的文件进行排序是否有意义(可能会占用太多内存!)。

【讨论】:

  • 对不起,我忘了提到 mmap.find() 不会给我带来内存问题。它只是没有正确匹配。
  • MSeifert,是的,您的代码有效。我给你投了赞成票,但它没有注册,因为我的声望低于 15。但是,您的代码比我上面发布的 mmap 解决方案要慢得多。我基本上错过了字符串中的 strip() ,这就是它没有进行匹配的原因。非常感谢:)
  • @Ali Ah,所以strip 不见了,至少在答案中有一些有用的东西。如果您自己找到了解决方案,您可以随时在此处发布其他答案。它可能对未来的读者有所帮助。
  • 我刚做了。与 unix diff 之类的东西相比,它仍然非常慢。您认为我在 mmap 中进行的搜索是最有效的方法还是有更好的选择?谢谢。
【解决方案2】:

处理不适合内存的文件总是很困难。

如果file1 适合内存但file2 太大,这里有一个解决方案:

# file1 and file2 are open file-like objects
unseen = set(file1)
for line in file2:
    unseen -= {line} # avoid exception from set.remove
#if unseen is empty, all lines were found in file2

否则,您应该至少对其中一个文件进行排序(或者可能是 CFBS 排序)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 2013-03-04
    相关资源
    最近更新 更多