Python 列表 - “保留”空间(~ 调整大小)

19 投票
4 回答
25853 浏览
提问于 2025-04-17 10:09

我有一个列表 l,我想给它赋值:

l[index] = val

但是,有时候这个列表可能太小了。

所以,我想确保有足够的空间来放新的值。

有时候我需要用空字符串 '' 来填充新空间,有时候则需要用其他对象(比如空列表 []FalseNone)来填充。

为此,我使用了以下方法:

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 个回答

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:]                  
6

我想到了一个使用 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']

这样对你有用吗?

编辑:因为问题更新了,我也更新了我的回答。

8

如果你确定使用列表(而不是像 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)。

这个类在你需要快速通过索引找到元素时特别有用,尤其是当你的数据结构比较紧凑的时候。如果你的数据结构比较稀疏,可能更适合使用字典。

撰写回答