【问题标题】:Populating a list/array by index in Python?在 Python 中按索引填充列表/数组?
【发布时间】:2010-10-26 13:37:56
【问题描述】:

这可能吗:

myList = []

myList[12] = 'a'
myList[22] = 'b'
myList[32] = 'c'
myList[42] = 'd'

当我尝试时,我得到:

# IndexError: list assignment index out of range # 

【问题讨论】:

  • myList = () 实际上是一个元组,你不能在元组中添加、删除或查找对象。
  • 是的,我实际上在代码中使用了 [],在这里搞混了。

标签: python list


【解决方案1】:

建立在三联画之上。如果你想要一个任意维度的列表

class dynamiclist(list):
    """ List not needing pre-initialization

    Example:
        l = dynamiclist()
        l[20][1] = 10
        l[21][1] = 20
    """

    def __setitem__(self, index, value):
        size = len(self)
        if index >= size:
            self.extend(dynamiclist() for _ in range(size, index + 1))

        list.__setitem__(self, index, value)

    def __getitem__(self, index):
        size = len(self)
        if index >= size:
            self.extend(dynamiclist() for _ in range(size, index + 1))  # allows dimensions > 1

        return list.__getitem__(self, index)

例子

l = dynamiclist()
l[20][1] = 10
l[21][1] = 20

【讨论】:

    【解决方案2】:

    以防万一有人需要,我想出了一个解决问题的方法,我需要计算很多阶乘,其中一些可以重复,所以在这里是我的解决方案:

    factorials = {}
    
    def calcFact(v):
        try:
            return factorials[v]
        except KeyError:
            factorials[v] = math.factorial(v)
            return factorials[v]
    

    测试用例:

    calcFact(99000)
    calcFact(90900)
    calcFact(90090)
    calcFact(90009)
    calcFact(90009) #repeated
    calcFact(90009) #repeated
    

    结果:

    重复数学计算:1.576 s

    使用上面的代码(存储重复值的列表):1.011 s

    【讨论】:

    • 这没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
    • @phineas 正如我在回答中所说,这是我需要解决的问题,这与“按索引填充列表/数组”有关,您可以通过阅读代码注意到。这是解决问题的方法,但使用不同的示例。
    【解决方案3】:

    这是一个快速列表包装器,如果您尝试将值分配给超过其长度的索引,它将自动用零扩展您的列表。

    class defaultlist(list):
    
       def __setitem__(self, index, value):
          size = len(self)
          if index >= size:
             self.extend(0 for _ in range(size, index + 1))
    
          list.__setitem__(self, index, value)
    

    现在你可以这样做了:

    >>> a = defaultlist([1,2,3])
    >>> a[1] = 5
    [1,5,3]
    >>> a[5] = 10
    [1,5,3,0,0,10]
    

    【讨论】:

    • 还要注意@Pithikos 将其扩展为任意维度的列表。
    【解决方案4】:

    如果你事先不知道列表的大小,你可以使用 try/except 然后在 except 中扩展列表:

    L = []
    def add(i, s):
        try:
            L[i] = s
        except IndexError:
            L.extend([None]*(i-len(L)+1))
            L[i] = s
    
    add(12, 'a')
    add(22, 'b')
    

    -- 更新 -------------------------- -------
    根据 tgray 的评论:如果您的代码大部分时间可能会抛出异常,则应每次检查 List 的长度,并避免出现异常:

    L = []
    def add(i, s):
        size = len(L)
        if i >= size:
            L.extend([None]*(i-size+1))
            L[i] = s
    

    【讨论】:

    • 如果他正在添加索引增加的项目,则可以通过使用“if”语句而不是“try-catch”来提高速度。在这种情况下,您每次都会捕获异常,这比每次检查 L 的长度更“昂贵”。
    • 您是否有指向来源的链接,说明它更“昂贵”?还是多少?那会很有帮助。
    • 这是我评论来源的链接:paltman.com/2008/jan/18/…
    【解决方案5】:

    除非在列表中的其他位置填充一些东西(如None 或空字符串)。尝试使用您编写的代码将元素插入到列表中会导致 IndexError

    还有mylist.insert,不过这个代码:

    myList.insert(12,'a')
    

    只会在列表中第一个未占用的位置插入“a”(使用您的示例将是 0)。

    所以,正如我所说,列表中必须有索引 0-11 的内容,然后才能在 myList[12] 处插入内容。

    【讨论】:

    • 确实,list.insert() 不是一个正确的解决方案,因为插入一个项目会移动所有其他索引。
    【解决方案6】:

    您必须先用一些东西(例如0None)预先填充它,然后才能对其编制索引:

    myList = [None] * 100  # Create list of 100 'None's
    myList[12] = 'a'  # etc.
    

    或者,使用字典而不是列表,如Alex Martelli suggested

    【讨论】:

      【解决方案7】:

      对于“稀疏列表”,您可以改用 dict

      mylist = {}
      mylist[12] = 'a'
      

      等等。如果你想要一个实际的列表(用[] 初始化它,not (),当然!-)你需要将未设置的插槽填充到_some_thing,例如None,通过一点辅助功能或通过子类化list

      【讨论】:

      • 从错误来看,我相信他实际上是在使用一个列表,而不是一个元组。
      • 调用您的字典mylist 可能不是最佳做法。
      • 谢谢我需要对项目进行线性访问,所以我可以从 1 到 n 进行索引,所以不能使用字典。
      • 当然可以,使用 dict 有很多方法可以做到这一点。即“for k in sorted(mydict.keys()): print mydict[k]”
      • 字典中从 1 到 n 的索引仍然有效。 for i in range(n): if n in dictionary: print dictionary[n] 做你想做的事。
      猜你喜欢
      • 2018-01-22
      • 1970-01-01
      • 2016-05-31
      • 1970-01-01
      • 2010-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多