【问题标题】:What is the most efficient way to compute the difference of lines from two files?计算两个文件的行差异的最有效方法是什么?
【发布时间】:2023-03-20 20:47:01
【问题描述】:

我在 python list_alist_b 中有两个列表。 list_a 有一些图片链接,list_b 也有。 99% 的项目都是一样的,但我必须知道这 1%。所有剩余项目都在list_a 中,这意味着list_b 中的所有项目都在list_a 中。我最初的想法是减去所有项目: list_a - list_b = list_c,其中list_c 是我的剩余物品。我的代码是:

list_a = []
list_b = []
list_c = []

arq_b = open('list_b.txt','r')
for b in arq_b:
    list_b.append(b)

arq_a = open('list_a.txt','r')
for a in arq_a:
    if a not in arq_b:
        list_c.append(a)

arq_c = open('list_c.txt','w')
for c in list_c:
    arq_c.write(c)

我认为逻辑是正确的,如果我有一些项目,代码运行得很快。但我没有 10 个项目,或 1.000,甚至 100.000。我的list_b.txt 中有78.514.022 项,我的列表list_a.txt 中有78.616.777。我不知道这个表达式的成本:if a not in arq_b。但是如果我执行这段代码,我认为不会在今年完成。

我的电脑有 8GB,我分配了 15GB 用于交换,以免我的 RAM 爆炸。

我的问题是,还有另一种方法可以让这个操作更高效(更快)吗?

  • list_a 是纵坐标,而list_b 不是。
  • 每个项目都有这个尺寸:images/00000cd9fc6ae2fe9ec4bbdb2bf27318f2babc00.png
  • 顺序无所谓,我想知道剩余的。

【问题讨论】:

  • 顺序重要吗?如果没有,请尝试使用集合。对于集合,减法应该是线性的:set_c = set_a - set_b.
  • 但是可以在 python 中实现吗?
  • python会用最高效的方式进行这个操作吗?
  • 是的,我的意思是 Python 数据类型 set
  • @tripleee 这不是重复的 - 这个问题是关于在列表上映射减法,这个问题是关于列表中包含的内容之间的区别。

标签: python python-3.x list performance difference


【解决方案1】:

尝试使用集合:

with open("list_a.txt") as f:
    set_a = set(f)

with open("list_b.txt") as f:
    set_b = set(f)

set_c = set_a - set_b

with open("list_c.txt","w") as f:
    for c in set_c:
        f.write(c)

两个集合相减的复杂度is O(n) in the size of the set a

【讨论】:

  • 你知道 - 打开的文件是一个迭代器 - 因此你可以简单地做set_a = set(open("list_a.txt"))
  • 是的,但是用块执行set(f) 确保它关闭文件
【解决方案2】:

扩展@L3viathan 的评论 如果元素的顺序不重要,则设置是正确的方法。 这是一个你可以适应的虚拟示例:

l1 = [0,1,2,3,4,5]
l2 = [3,4,5]
setL1 = set(l1)  # transform the list into a set
setL2 = set(l2)
setDiff = setl1 - setl2  # make the difference 
listeDiff = list(setDiff)  # if you want to have your element back in a list

如您所见,在 python 中非常简单。

【讨论】:

    【解决方案3】:

    您可以创建一组第一个文件内容,然后只需使用 differencesymmetric_difference,具体取决于您所说的差异

    with open("list_a.txt") as f:
        set_a = set(f)
    
    with open("list_b.txt") as f:
        diffs = set_a.difference(f)
    

    如果list_b.txt 包含的项目多于list_a.txt,您希望交换它们或改用set_a.symmetric_difference(f),具体取决于您的需要。

    difference(f) 可以工作,但仍需要在内部构造一个新的set。性能提升不是很大(请参阅set issubset performance difference depending on the argument type),但它更短。

    【讨论】:

    • 很好,这样可以避免为第二组分配空间。
    • 嗯,不是真的,因为在内部创建了一个set,然后被丢弃。但它被扔掉了更快
    • 但是减法集的复杂度是一样的吗?
    • @ViniciusMorais 时间复杂度是一样的,空间复杂度(显然)也是。
    • @L3viathan 如果不再需要原始列表(原始集),您可以使用difference_update。这不应该需要在内部分配一个新的集合。
    【解决方案4】:

    如果顺序很重要,您可以将列表与项目索引一起预排序,然后一起迭代它们:

    list_2 = sorted(list_2)
    diff_idx = []
    j = 0
    for i, x in sorted(enumerate(list_1), key=lambda x: x[1]):
        if x != list_2[j]:
            diff_idx.append(i)
        else:
            j += 1
    diff = [list_1[i] for i in sorted(diff_idx)]
    

    这具有排序算法的时间复杂度,即 O(n*log n)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-10
      • 2011-07-13
      • 2020-11-13
      • 2018-12-07
      • 1970-01-01
      • 2011-01-26
      相关资源
      最近更新 更多