首页 > 解决方案 > 为什么我的数组的元素被覆盖?

问题描述

我在 Python 中编写了一个简单的函数,旨在通过在其中一个数组中交换最多一对元素来从两个元素a和中找到一个。b

这是我的功能:

def areSimilar(a, b):
    test = 0
    for i in range(len(b)):
        for j in range(len(b)):
            b2 = b
            b2[i] = b[j]
            b2[j] = b[i]
            if a == b2:
                test = 1
    return(test==1)

问题是,在检查b时,即使我实际上没有执行任何计算,它也发生了变化b——发生了什么事!!??

标签: python-3.x

解决方案


(已编辑:为了更好地解决第二点)

您的代码有两个问题:

  • 当您这样做时,b2 = b只会创建对基础对象的另一个引用。如果b是可变的,对 的任何更改b2也将反映在b其中。
  • 当一次交换就足够时,不需要进一步测试,但如果你继续循环测试将再次成功ij交换,所以test条件要么永远不会命中,要么(至少 - 取决于重复的数量)两次。虽然这不会导致错误的结果,但通常会被视为逻辑错误。

要修复您的代码,您只需创建一个b. 假设您所说的 Python 数组实际上是指 Pythonlist的一种方法,那就是list每次都通过替换b2 = bb2 = list(b). 一种更有效的方法是对b自身执行交换(并交换回):

def are_similar(a, b):
    for i in range(len(b)):
        for j in range(len(b)):
            b[i], b[j] = b[j], b[i]
            if a == b:
                b[i], b[j] = b[j], b[i]  # swap back
                return True
            else:
                b[i], b[j] = b[j], b[i]  # swap back
    return False


print(are_similar([1, 1, 2, 3], [1, 2, 1, 3]))
# True
print(are_similar([1, 1, 2, 3], [3, 2, 1, 1]))
# False

相比之下,您可以看到基于复制的方法是多么低效(虽然正确):

def are_similar2(a, b):
    for i in range(len(b)):
        for j in range(len(b)):
            b2 = list(b)
            b2[i] = b[j]
            b2[j] = b[i]
            if a == b2:
                return True
    return False


print(are_similar2([1, 1, 2, 3], [1, 2, 1, 3]))
# True
print(are_similar2([1, 1, 2, 3], [3, 2, 1, 1]))
# False

即使在相对较小的输入上,时间也要差得多:

a = [1, 1, 2, 3] + list(range(100))
b = [1, 2, 1, 3] + list(range(100))
%timeit are_similar(a, b)
# 10000 loops, best of 3: 22.9 µs per loop
%timeit are_similar2(a, b)
# 10000 loops, best of 3: 73.9 µs per loop

推荐阅读