Python列表 - “预留”空间(〜大小调整)

时间:2012-01-13 11:26:14

标签: python python-3.x

我获得了一个列表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, [])

有更多的pythonic方式吗?这样做是否有一些内置函数或库函数?

我主要使用的是Python-3.x,但有关Python-2x的专业知识非常有用且受欢迎。

澄清:请不要告诉我dict,因为我需要list

对于那些希望我更具体的人:

问题陈述表明它是关于list类型的。在这里使用dict不是一个选项或解决方案。有理由,特别是与域有关(我正在做一个实验的原型,必须显示一些渐近行为, - 可能你已经习惯了 - 程序的原型如果它只是“程序的原型”,那么我同意使用dict和其他评论)。我有以下假设:

  • 我有很多列表(需要关心内存和性能开销)
  • 由于工作流程和原型的需要,我无法调用手动编码的C / C ++扩展
  • 在计算过程中最终列表大小未知
  • 我们知道在列表中密集
  • 列表单元格以未知顺序写入和覆盖

这些只是我强调我需要list而不是dict的几个原因。 对于那些对更多详细信息感兴趣或想要讨论dictcheckout how we discuss in comments HERE

的人

4 个答案:

答案 0 :(得分:7)

如果您确定列表 - 而不是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测试)。

如果结构密集且您需要尽快按索引查找元素,则此类可能很方便。如果结构稀疏,您应该考虑使用字典。

答案 1 :(得分:3)

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

这对你有用吗?

修改:由于问题已更新,我已更新答案。

答案 2 :(得分:3)

也许这就是你想要的:

def resize(l, newsize, filling=None):                                                                                  
    if newsize > len(l):                                                                                 
        l.extend([filling for x in xrange(len(l), newsize)])                                                 
    else:                                                                                                
        del l[newsize:]                  

答案 3 :(得分:2)

试试这个:

def ResizeList(some_list, length, null_item = None): 
    return some_list + [null_item 
                        for item in range(length - len(lst))]