我在Python中计算求和区域表(https://en.wikipedia.org/wiki/Summed_area_table)时遇到问题。最明显的算法涉及在引用已经编写的元素时更新列表元素......但是有关就地更新的内容似乎让Python感到困惑。
以下是一些示例代码:
def compute_summed_area_table(image):
# image is a 2-dimensional array containing ints or floats, with at least 1 element.
height = len(image)
width = len(image[0])
new_image = [([0.0] * width)] * height # Create an empty summed area table
for row in range(0, height):
for col in range(0, width):
if (row > 0) and (col > 0):
new_image[row][col] = image[row][col] + \
new_image[row][col - 1] + new_image[row - 1][col] - \
new_image[row - 1][col - 1]
elif row > 0:
new_image[row][col] = image[row][col] + new_image[row - 1][col]
elif col > 0:
new_image[row][col] = image[row][col] + new_image[row][col - 1]
else:
new_image[row][col] = image[row][col]
# Note that two-pass code gives the same kind of results, e.g.:
# for row in range(0, height):
# for col in range(0, width):
# if col > 0:
# new_image[row][col] = image[row][col] + new_image[row][col - 1]
# else:
# new_image[row][col] = image[row][col]
# for row in range(0, height):
# for col in range(0, height):
# if row > 0:
# new_image[row][col] += new_image[row - 1][col]
return new_image
small_image = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25]]
small_sat = compute_summed_area_table(small_image)
print(small_sat)
基于我自己的手动计算(可能出错),此测试代码应该提供如下内容: [[1,3,6,10,15],[7,16,27,40,55],[18,39,63,90,120],[34,72,114,160,210],[ 55,115,180,250,325]]
相反,它给出: [[55,61,68,76,85],[55,61,68,76,85],[55,61,68,76,85],[55,61,68,76,85],[ 55,61,68,76,85]]
显然在每次迭代期间更新每一行,但我不确定为什么或如何。有谁知道究竟出了什么问题?还有其他方法可以进行就地更新吗?如果没有,你会怎么做?
答案 0 :(得分:2)
这是因为
new_image = [([0.0] * width)] * height
您没有创建尺寸宽度和高度的二维列表,而是创建高度项列表,并且该列表中的所有元素都指向大小宽度列表(它们都指向相同的列表)。解决此问题
new_image = [[0.0] * width for _ in range(height)]
考虑这个例子,
a = [[0] * 3] * 2
a[0][0] = 1
print a
a = [[0] * 3 for _ in range(2)]
a[0][0] = 1
print a
<强>输出强>
[[1, 0, 0], [1, 0, 0]]
[[1, 0, 0], [0, 0, 0]]
在第一种情况下,a[0]
和a[1]
指向同一个列表。因此,将元素更改为0,也将元素更改为1。