Python 列表 - “保留”空间(~ 调整大小)
我有一个列表 l
,我想给它赋值:
l[index] = val
但是,有时候这个列表可能太小了。
所以,我想确保有足够的空间来放新的值。
有时候我需要用空字符串 ''
来填充新空间,有时候则需要用其他对象(比如空列表 []
、False
或 None
)来填充。
为此,我使用了以下方法:
def ResizeList(l, size, fill_with=None):
l += [fill_with]*(size-len(l))
(注意:即使 size-len(l)<=0
,这个方法也能正常工作)
(注意:因为我关注的是保留空间,所以我故意不缩短列表的长度)
像这样:
ResizeList(l, index+1)
l[index] = val
(当用其他对象填充时,就像是: ResizeList(l, index+1, [])
)
有没有更符合 Python 风格的方法来做到这一点?有没有一些内置函数或库函数可以用来实现这个?
我主要使用 Python-3.x,但对 Python-2.x 的知识也很欢迎。
澄清一下:请不要告诉我关于 dict
的事,因为我需要 list
对于那些希望我更具体的人:
问题说明中提到的是 list
类型。在这里使用 dict
不是一个选项或解决方案。这样做有原因,特别是与我的领域相关(我正在做一个实验的原型,需要展示一些渐近行为,而不是像你们习惯的那样做一个程序的原型。如果只是“程序的原型”,那么我同意使用 dict
和其他评论)。我有以下假设:
- 我有很多很多的列表(需要关注内存和性能开销)
- 由于工作流程和原型的需要,我不能调用手写的 C/C++ 扩展
- 在计算过程中,最终列表的大小是未知的
- 我们知道最终列表会是密集的
- 列表单元格的写入和覆盖顺序是未知的
这些只是我强调需要 list
而不是 dict
的几个原因。
对于那些想了解更多细节或想讨论 dict
的人,可以查看我们在评论中的讨论
4 个回答
也许这个代码可以实现你想要的效果:
def resize(l, newsize, filling=None):
if newsize > len(l):
l.extend([filling for x in xrange(len(l), newsize)])
else:
del l[newsize:]
我想到了一个使用 itertool.repeat()
的方法。
import itertools
def assign(lst, idx, value, fill=None):
diff = len(lst) - idx
if diff >= 0:
lst[idx] = value
else:
lst.extend(itertools.repeat(fill, -diff))
lst.append(value)
这个方法有以下的表现:
>>> l = [0, 1, 2, 3, 4]
>>> assign(l, 2, 'new')
>>> l
[0, 1, 'new', 3, 4]
>>> assign(l, 8, 'new')
>>> l
[0, 1, 'new', 3, 4, None, None, None, 'new']
>>> assign(l, 10, 'new', fill=[])
>>> l
[0, 1, 'new', 3, 4, None, None, None, 'new', [], 'new']
这样对你有用吗?
编辑:因为问题更新了,我也更新了我的回答。
如果你确定使用列表(而不是像 dict
这样的其他数据结构)最适合你的需求,我建议你可以使用下面这个类:
class rlist(list):
def __init__(self, default):
self._default = default
def __setitem__(self, key, value):
if key >= len(self):
self += [self._default] * (key - len(self) + 1)
super(rlist, self).__setitem__(key, value)
l = rlist(0)
print(l)
l[10] = 20
print(l)
l[5] = 14
print(l)
这个类会检查你要赋值的索引是否超出了当前列表的长度,如果超出了,它会自动扩展列表。
这段代码在Python 2和3中都可以使用(我测试过2.6.5和3.1.2)。
这个类在你需要快速通过索引找到元素时特别有用,尤其是当你的数据结构比较紧凑的时候。如果你的数据结构比较稀疏,可能更适合使用字典。