我在python中创建了一大堆元素,我将打印到Excel电子表格中。顺序和最终维度在某种程度上是可以预测的,但对它们进行硬编码本质上是脆弱的。我想找到一种动态调整数组大小的方法,如果它不够大的话。
添加元素的顺序可能不是顺序的,因此追加不能直接起作用。我需要能够在2D数组中分配任何元素,并调整数组大小以处理它,如下所示:
data = magic_array()
data[3][5] = 35
是否存在允许此行为的内置功能?如果没有,你能推荐一个好方法来实现吗?
答案 0 :(得分:5)
您可以创建自定义DefaultList
类,类似于collections.defaultdict
,因为它需要default_factory
个参数:
class DefaultList(list):
def __init__(self, default_factory, *args, **kwargs):
super().__init__(*args, **kwargs)
self.default_factory = default_factory
def _extend(self, index):
while len(self) <= index:
self.append(self.default_factory())
def __getitem__(self, index):
self._extend(index)
return super().__getitem__(index)
def __setitem__(self, index, value):
self._extend(index)
super().__setitem__(index, value)
要在您的情况下使用它,您可以创建一个二维实例,default_factory
只创建另一个DefaultList(int)
:
>>> L = DefaultList(lambda: DefaultList(int))
>>> L[3][2] = 1
>>> L
[[], [], [], [0, 0, 1]]
虽然我更喜欢使用带有2D元组的defaultdict
作为键:
>>> import collections
>>> d = collections.defaultdict(int)
>>> d[2, 3] = 1
>>> d[0, 0]
0
>>> d[2, 3]
1
这比DefaultList
占用更少的内存,并且应该更快,因为它只创建我们实际访问的元素(而不是索引0和我们访问的那个之间的所有内容)。如果您需要将其打印为2D地图,则只需创建自定义__str__
方法,但我会留给您。
这种方法的另一个优点是你可以有一个点P = (x, y)
而你不必L[P[1]][P[0]]
来访问一个元素,但是你可以d[P]
键是点。哦,因此您可以在x
之前使用y
以自然顺序访问它们,以便:
L[2][1] == d[1, 2]
x=1
和y=2
答案 1 :(得分:0)
要添加@MarkusMeskanen的优秀答案,将默认字典转换为列表列表相当容易:
def to_array(d):
m = max(d.keys())[0]
n = max(d.keys(),key = lambda x: x[1])[1]
A = []
for i in range(m+1):
A.append([0]*(n+1))
for i,j in d.keys():
A[i][j] = d[i,j]
return A
例如,
>>> d = defaultdict(int)
>>> d[3,2] = 5
>>> to_array(d)
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 5]]
他列出的默认值的优点超过了在加载数据时需要使用上述函数的缺点,特别是因为您可能需要根据其他方法进行一些转换,因为可能某些行可能是空了,需要扩大。
答案 2 :(得分:-1)
您想要将数据发送到二维接收器。但这并不意味着您的程序需要使用二维数据结构。您已经发现列表列表对于您想要执行的操作很笨重。
放弃二维数据结构并在内部将数据存储为dict
,其中包含(x,y)元组的键。
mydict = {}
mydict [(3,5)] = 35
在您要填充Excel电子表格的位置,循环浏览dict
for (row,col), data in mydict.items():
# update Excel row 3, column 5 with 35
这在其他方向也同样有效。