生成器函数,用于查找两个文件之间的公共行

问题描述 投票:0回答:2

我正在阅读 Steven 和 Dusty 的 Python 面向对象编程

我在第 10 章,都是关于迭代器设计模式的。本章末尾有一个练习,编写生成器函数/表达式以查找两个文件之间的公共行。

这是我天真的方法:

old = os.path.normpath('E:/testing/old.txt')
new = os.path.normpath('E:/testing/new.txt')
res = []

def func(source):
    for line in source.readlines():
        yield line

方法一:

with open(old, "r") as f:
    for line in func(f):
        with open(new, "r") as _f:
            for _line in func(_f):
                if line == _line:
                    res.append(line)

方法二:

with open(old, "r") as f:
    for line in func(f):
        with open(new, "r") as _f:
            res.extend(filter(lambda a: line == a, func(_f)))

上下文:

现在,让我们考虑完全不同的问题,假设我们有字符串列表而不是带有

n
m
元素的文件,我们可以在
O(n)
时间复杂度和
O(m)
空间中找到常见字符串。

大问题

  1. 是否有更好的 pythonic 方法来重构上述代码?
  2. 我知道生成器都是为了节省spacestate,但是按照上面的context,在时间复杂度方面有没有更好的方法来比较两个文件并找到公共行。

我的最终目标是在时间和空间复杂度方面优化我的代码(如果可能的话),并使其更像 pythonic。

附言- 谁能给我指点 linux

diff
命令和
git-diff
源代码的源代码。

我试图找到 linux

diff
git-diff
的源代码,但找不到。

python iterator generator
2个回答
1
投票

我不认为使用生成器可以最好地解决这个问题。我的方法是:

old = 'E:/testing/old.txt'
new = 'E:/testing/new.txt'

with open(old) as f:
    old_lines = set(f) # A set of lines

with open(new) as f:
    matches = [line for line in f if line in old_lines]

print(matches)

如果你想比较去掉尾随换行符的行(因为最后一行可能没有尾随换行符),那么你可以使用下面的代码,它也演示了创建两个集合并对它们进行“交集”操作。这样您就不必显式地循环遍历行。但是,您无法控制打印匹配项的顺序:

old = 'E:/testing/old.txt'
new = 'E:/testing/new.txt'

with open(old) as f:
    old_lines = set(line.strip('\n') for line in f) # A set of lines

matches = []
with open(new) as f:
    matches = set(line.strip('\n') for line in f) and old_lines

print(matches)

0
投票

如果我是你,我会使用

set
,他们可以在(几乎)恒定的时间内进行会员测试。
some_set.intersection(some_other_set)
产生他们的共同成员。它真的很快因为他们使用哈希表.

© www.soinside.com 2019 - 2024. All rights reserved.