【问题标题】:How to set a max length for a python list/set?如何为 python 列表/集设置最大长度?
【发布时间】:2013-07-05 18:52:49
【问题描述】:

在 c/c++ 中,我们可以:

maxnum = 10;
double xlist[maxnum];

如何设置 python 列表/集合的最大长度?

【问题讨论】:

  • 这样我就可以将我的贪婪搜索限制在前 x 个结果中。否则在 x 之后继续追加、排序然后删除元素有点浪费
  • 一种方法是创建自定义列表类并从 python list 继承功能。然后在add(可能还有其他)方法中添加最大长度检查。
  • @stalk 您应该将其发布为答案。

标签: python list max maxlength


【解决方案1】:

你可以使用这个先分配内存的解决方案

[0] * maxnum

或

[a sample of your object] * maxnum

请注意,如果附加超过列表的最大大小,此解决方案不会引发诸如 c++ 语言之类的错误

【讨论】:

    【解决方案2】:

    这里是 python 的list 的扩展版本。它的行为类似于 list,但如果超过长度(在 python 2.7 中尝试),则会引发 BoundExceedError:

    class BoundExceedError(Exception):
        pass
    
    
    class BoundList(list):
        def __init__(self, *args, **kwargs):
            self.length = kwargs.pop('length', None)
            super(BoundList, self).__init__(*args, **kwargs)
    
        def _check_item_bound(self):
            if self.length and len(self) >= self.length:
                raise BoundExceedError()
    
        def _check_list_bound(self, L):
            if self.length and len(self) + len(L) > self.length:
                raise BoundExceedError()
    
        def append(self, x):
            self._check_item_bound()
            return super(BoundList, self).append(x)
    
        def extend(self, L):
            self._check_list_bound(L)
            return super(BoundList, self).extend(L)
    
        def insert(self, i, x):
            self._check_item_bound()
            return super(BoundList, self).insert(i, x)
    
        def __add__(self, L):
            self._check_list_bound(L)
            return super(BoundList, self).__add__(L)
    
        def __iadd__(self, L):
            self._check_list_bound(L)
            return super(BoundList, self).__iadd__(L)
    
        def __setslice__(self, *args, **kwargs):
            if len(args) > 2 and self.length:
                left, right, L = args[0], args[1], args[2]
                if right > self.length:
                    if left + len(L) > self.length:
                        raise BoundExceedError()
                else:
                    len_del = (right - left)
                    len_add = len(L)
                    if len(self) - len_del + len_add > self.length:
                        raise BoundExceedError()
            return super(BoundList, self).__setslice__(*args, **kwargs)
    

    用法:

    >>> l = BoundList(length=10)
    >>> l.extend([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    >>> l
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    >>> # now all these attempts will raise BoundExceedError:
    >>> l.append(11)
    >>> l.insert(0, 11)
    >>> l.extend([11])
    >>> l += [11]
    >>> l + [11]
    >>> l[len(l):] = [11]
    

    【讨论】:

    • 我需要导入什么库什么的吗?
    【解决方案3】:

    你不能,列表和集合本质上是动态的,可以增长到任何大小。

    Python 不是 c++,python 是一种动态语言。集合和列表可以扩展或缩小到任意大小。

    如果你想从一个可迭代对象中获得 x 个最小或最大的项,请使用 heapq 模块。

    heapq.nsmallest(n, iterable[, key])
    

    从定义的数据集中返回一个包含 n 个最小元素的列表 可迭代的。键(如果提供)指定一个参数的函数 用于从可迭代的每个元素中提取比较键: key=str.lower 等价于:sorted(iterable, key=key)[:n]

    或者可能是bisect模块:

    此模块支持按排序顺序维护列表 无需在每次插入后对列表进行排序。

    然后使用切片或itertools.slice 从列表中获取前 x 个项目。

    【讨论】:

      【解决方案4】:

      你不需要也不需要。

      Python 列表根据需要动态增长和收缩以适应其内容。集合以哈希表的形式实现,并且像 Python 字典一样根据需要动态增长和收缩以适应其内容。

      也许您正在寻找 collections.deque(它采用 maxlen 参数)或使用 heapq 的东西(当您达到最大值时使用 heapq.heappushpop())?

      【讨论】:

      • 我认为您对缩小字典的看法是错误的,或者至少它有些误导。当我创建一个空字典时,sys.getsizeof 告诉我它是 148 个字节。添加一百万个条目后,它是 25165876 字节。弹出所有条目后,它仍然是 25165876 字节。另外,如果我尝试next(iter(d)),在添加一百万个条目后,它比弹出除一个之外的所有条目快约 3500 倍(这实际上是我注意到这一点的方式)。
      • @StefanPochmann 调整大小将推迟到您再次添加某些内容(IIRC)。我需要检查确切的触发器是什么。我确实知道删除最常见的用法通常是新添加,这是优化的,因此删除时不会立即收缩。
      • @StefanPochmann 不在笔记本电脑上,但 Tim Peters 的这封电子邮件解释了插入如何触发调整大小:mail.python.org/pipermail/python-dev/1999-August/000667.html。
      • @MartijnPieters 谢谢,虽然可能不再正确。当我再次添加项目时,我的 dict 保持在 25,165,876 字节,直到它最终跳转到 50,331,700 字节。 This comment 在当前代码中确实说“新表实际上可能比旧表小”,但我实际上无法实现这一点。
      • @StefanPochmann:它仍然是最新的,但我还没有研究触发调整大小的所有方法。搜索实际调用 dictresize 的位置。
      【解决方案5】:

      一旦你有了你的名单,lst,你就可以

      if len(lst)>10:
          lst = lst[:10]
      

      如果大小超过 10 个元素,则截断到前十个元素。

      【讨论】:

      • 正如@JonasR 指出的那样,在截断之前检查len(lst) 是多余的。
      • 试试这个代码x=[1,2,6]; x = x[:2] if len(x)>2 else x然后试试这个代码x=[1,2,6]; x[:2]
      猜你喜欢
      • 2012-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-20
      • 1970-01-01
      • 2011-02-01
      • 2012-09-27
      • 1970-01-01
      相关资源
      最近更新 更多