【问题标题】:how to compare two list and find out `added` `deleted` `unchanged ` part如何比较两个列表并找出“已添加”“已删除”“未更改”部分
【发布时间】:2020-07-05 14:49:31
【问题描述】:

我想要这个:

def compare_list(old, new):
    new_set = set(new)
    old_set = set(old)
    return new_set - old_set, old_set - new_set, new_set & old_set

old = [1, 2, 3]
new = [5, 4, 2, 3]

added, deleted, unchanged = compare_list(old, new)

print("added: ", added)
print("deleted: ", deleted)
print("unchanged: ", unchanged)

added:  {4, 5}
deleted:  {1}
unchanged:  {2, 3}

但这对我来说似乎效率很差。所以我想知道任何更有效的解决方案?还是内置函数?

【问题讨论】:

  • 这对我来说似乎很优雅。您如何确定效率低下?
  • @MarkMeyer 抱歉,我用错了词。我想知道它可以通过for循环O(N)来实现
  • 这个解决方案是 O(N)。同样,这个解决方案到底有什么问题?这是使用内置功能的直接方式。对我来说似乎很好。
  • @juanpa.arrivillaga 我正在尝试创建一个看起来像WinMerge 的查找差异软件,在我的程序中,有很多地方使用这个compare_list 函数,它看起来像底部脖子给我。因此,我正在寻找一种有效的解决方案来提高性能。 new_set - old_set, old_set - new_set, new_set & old_set 似乎在做相关的过程。
  • @JustWe 列表中每个元素的取值范围是否有界限?

标签: python list algorithm


【解决方案1】:

在 Python 中,您可以通过将较小的交集与两个较大的列表进行比较而不是将它们相互比较来获得额外的速度。

def compare_list2(old, new):
    new_set = set(new)
    old_set = set(old)
    inter = new_set & old_set
    return new_set - inter, old_set - inter, inter

old = [1, 2, 3]
new = [5, 4, 2, 3]

#%time added, deleted, unchanged = compare_list(old, new)
start_time = time.time()
for i in range(10000000):
    compare_list2(old, new)
print("--- %s seconds ---" % (time.time() - start_time))

仅计算一次交点并使用两次,比您的函数快 0.3 秒。

--- 6.982441663742065 seconds ---
vs
--- 7.270233154296875 seconds ---

关于时间复杂度,我们仍然需要对数据进行 3 次遍历。我们可以先排序,然后进行单次传递,得到O(n log n)。 Python 伪代码,速度要慢得多,但可以使用 C 实现。排序后,这将是O(n)

def compare_single_pass(old,new):
    new_set = sorted(new)
    old_set = sorted(old)
    added, deleted, unchanged = [],[],[]
    i, j = 0, 0
    j_max = len(old_set)
    i_max = len(new_set)
    while True:
        if i == i_max and j == j_max:
            return added, deleted, unchanged
            break
        if j == j_max:
            added.append(new_set[i])
            i += 1
            continue
        if i == i_max:
            deleted.append(old_set[j])
            j += 1
            continue
        if new_set[i] < old_set[j]:
            added.append(new_set[i])
            i += 1
            continue
        if new_set[i] == old_set[j]:
            unchanged.append(new_set[i])
            i += 1
            j += 1
            continue
        if new_set[i] > old_set[j]:
            deleted.append(old_set[j])
            j += 1
            continue

【讨论】:

  • 我很确定 O(n log n) 比 O(3n) 慢(转换为 O(n) )
猜你喜欢
  • 1970-01-01
  • 2010-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
相关资源
最近更新 更多