我正在使用以下类来创建表格,我需要找到一种方法,不仅可以加快速度,还可以更快地与它进行交互:
class Table(object):
"""a three dimensional table object"""
def __init__(self, xsize=1, ysize=1, zsize=1):
self.xsize = xsize
self.ysize = ysize
self.zsize = zsize
self.data = [0] * (xsize * ysize * zsize)
def __getitem__(self, key):
x, y, z = self.__extractIndices(key)
return self.data[x + self.xsize * (y + self.ysize * z)]
def __setitem__(self, key, value):
x, y, z = self.__extractIndices(key)
self.data[x + self.xsize * (y + self.ysize * z)] = value
def __extractIndices(self, key):
x = y = z = 0
if (self.ysize > 1):
if (self.zsize > 1):
if len(key) != 3:
raise IndexError
else:
x, y, z = key
elif len(key) != 2:
raise IndexError
else:
x, y = key
elif not isinstance(key, int):
raise IndexError
else:
x = key
return (x, y, z)
def resize(self, xsize=1, ysize=1, zsize=1):
"""resize the table preserving data"""
oldlist = list(self.data)
self.data = [0] * (xsize * ysize * zsize)
self.xsize = xsize
self.ysize = ysize
self.zsize = zsize
for i in range(0, oldlist):
self.data[1] = oldlist[i]
在某一点上,我需要找出两个列表中的数据是否等同于每个z
所以我这样做了self.data
和self.map.data
是上面的表类实例
for x in range(self.map.width - 1):
for y in range(self.map.height - 1):
tempflag = False
#layer 1
if self.data[x, y, 0] != self.map.data[x, y, 0]:
tempflag = True
layer1flag = True
#layer 2
if self.data[x, y, 1] != self.map.data[x, y, 1]:
tempflag = True
layer2flag = True
#layer 3
if self.data[x, y, 2] != self.map.data[x, y, 2]:
tempflag = True
layer3flag = True
#copy the data if it changed
if tempflag:
self.data = copy.deepcopy(self.map.data)
previewflag = True
显然,这是我可以想到的最慢的方式,并且考虑到我正在比较的这些表中的一些具有200 * 200 * 3 = 120,000个条目的大小。我需要尽可能快。
我考虑过重写上面的比较来切割一个z的所有条目,如此
tempflag = False
#layer 1
slicepoint1 = 0
slicepoint2 = self.data.xsize * self.data.ysize * 1
data1 = self.data.data[slicepoint1:slicepoint2]
data2 = self.map.data.data[slicepoint1:slicepoint2]
if data1 != data2:
tempflag = True
layer1flag = True
#layer 2
slicepoint1 = self.data.xsize * self.data.ysize * 1
slicepoint2 = self.data.xsize * self.data.ysize * 2
data1 = self.data.data[slicepoint1:slicepoint2]
data2 = self.map.data.data[slicepoint1:slicepoint2]
if data1 != data2:
tempflag = True
layer2flag = True
#layer 3
slicepoint1 = self.data.xsize * self.data.ysize * 2
slicepoint2 = self.data.xsize * self.data.ysize * 3
data1 = self.data.data[slicepoint1:slicepoint2]
data2 = self.map.data.data[slicepoint1:slicepoint2]
if data1 != data2:
tempflag = True
layer3flag = True
#copy the data if it changed
if tempflag:
self.data = copy.deepcopy(self.map.data)
previewflag = True
虽然这似乎会更快,但似乎仍然可以显着改善。例如,可以不使用numpy在Table类中构建数据列表吗?
我需要这个类,这个检查尽可能快地运行
如果使用numpy可以让我快速遍历表格,那么我也可以使用它中的数据进行blit操作来构建tilemap
我做需要保留表类的通用接口,尤其是表数据存储在self.data中的事实
总结使用numpy可以提高操作速度吗?如果是这样我该怎么办?
答案 0 :(得分:2)
我想是的,通过使用numpy你可能会获得很多速度。
您不仅可以制作切片,还可以制作矩形,也可以制作立方切片,例如:
>>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a[:2,1:]
array([[2, 3],
[5, 6]])
我不确定你想要完成什么,但你也可以轻松地比较numpy数组元素:
>>> numpy.array([1,2,3])==numpy.array([9,2,3])
array([False, True, True], dtype=bool)
如果您有更多问题,请随时发表评论。
答案 1 :(得分:1)
这绝对是NumPy的应用程序!它不仅可以加快代码速度,还可以大大简化代码,因为索引和比较已经由NumPy处理。你将不得不阅读一些教程来学习NumPy - 在这种情况下只需要一些提示就可以了解。
通常,我只是从numpy.ndarray
派生来定义自定义数组类,但是您声明您确实需要data
属性,该属性与numpy.ndarray.data
冲突。你的课程简化为
class Table(object):
def __init__(self, xsize=1, ysize=1, zsize=1):
self.data = numpy.zeros((xsize, ysize, zsize))
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def resize(self, xsize=1, ysize=1, zsize=1):
# This only works for increasing the size of the data,
# but is easy do adapt to other cases
newdata = numpy.zeros((xsize, ysize, zsize))
shape = self.data.shape
newdata[:shape[0], :shape[1], :shape[2]] = self.data
self.data = newdata
您的比较代码简化为
eq = self.data == self.data.map
layerflags = eq.reshape(-1, 3).any(axis=0)
if layerflags.any():
self.data[:] = self.map.data
它也会更快 !