如果索引不存在,则在Python列表中设置索引处的值

19

在Python中是否有一种方法、库或其他东西可以使我在列表中设置不存在的索引处的值?就像在运行时创建列表索引:

有没有一种方法、库或其他东西在Python中允许我在列表中设置一个不存在的索引值呢?就好像在运行时创建列表索引一样:

l = []
l[3] = 'foo'
# [None, None, None, 'foo']

而且更进一步地,带有多维列表:

l = []
l[0][2] = 'bar'
# [[None, None, 'bar']]

或者使用现有的一个:

l = [['xx']]
l[0][1] = 'yy'
# [['xx', 'yy']]

如果你正在寻找类似于自动初始化的功能,def tree(): return defaultdict(tree) 可以给你一个字典,当你请求一个不存在的条目时,它会递归地创建新的字典。 - user2357112
有没有什么理由你不能只使用字典?我看到的唯一区别是较低的索引被初始化为None。 - Ron
4个回答

16

虽然没有内置的功能,但实现起来非常容易:

class FillList(list):
    def __setitem__(self, index, value):
        try:
            super().__setitem__(index, value)
        except IndexError:
            for _ in range(index-len(self)+1):
                self.append(None)
            super().__setitem__(index, value)

或者,如果你需要改变现有的普通列表:

def set_list(l, i, v):
      try:
          l[i] = v
      except IndexError:
          for _ in range(i-len(l)+1):
              l.append(None)
          l[i] = v

2
多维数组很难处理...假设你想要在某些情况下l[i]不存在的时候设置为None,那么l[3] = 'three'会创建出[None, None, None, 'three']。但是当你执行l[0][3]时,当查找l[0]时,代码并不知道你想再次取消引用它,所以它并不知道将None更改为字典,并且失败了。任何多维解决方案都存在一个问题,即无法读取思维... - Corley Brigman

4

不是百分百的可靠,但似乎最简单的方法是初始化一个比你需要的列表长度要更大的列表。

l = [None for i in some_large_number]
l[3] = 'foo'
# [None, None, None, 'foo', None, None None ... ]

3
如果您真的需要问题中的语法,defaultdict 可能是获取它的最佳方式。
from collections import defaultdict
def rec_dd(): 
    return defaultdict(rec_dd)

l = rec_dd()
l[3] = 'foo'

print l
{3: 'foo'}

l = rec_dd()
l[0][2] = 'xx'
l[1][0] = 'yy'
print l
<long output because of defaultdict, but essentially)
{0: {2: 'xx'}, 1: {0: 'yy'}}

它不完全是一个'列表的列表',但它的工作方式差不多像一个。

然而,你确实需要指定使用情况...上述方法有一些优点(你可以直接访问索引而无需首先检查它们是否存在),也有一些缺点-例如,在普通字典中,l[2]会返回一个KeyError,但在defaultdict中,它只会创建一个空白的defaultdict,将其添加,并返回它。

支持不同语法糖的其他可能实现可能涉及自定义类等,并且将具有其他权衡。


这很好,但我需要一个数组。你能展示一下如何将它转换成一个吗? - user1538560
如果你需要一个数组...你应该使用一个数组。然而,在它被填充后,你可以做像 for index in range(10): do_something(l[index]) 这样的事情 - 也就是说,即使它看起来不像一个数组,对于大多数用途来说,它表现得像一个数组。但是,你需要定义如果 l[i] 不存在意味着什么 - 这将创建一个空的 defaultdict 对象,但很可能如果你看到这个,你的算法中已经有一些 bug 了。 - Corley Brigman

1

你不能创建一个有空隙的列表。你可以使用一个 dict 或者这个快速的小家伙:

def set_list(i,v):
    l = []
    x = 0
    while x < i:
        l.append(None)
        x += 1
    l.append(v)
    return l

print set_list(3, 'foo')
>>> [None, None, None, 'foo']

但是如果我想要添加到一个已经存在的列表中呢?例如: set_list(['a', 'b'], 3, 'foo') # ['a', 'b', None, 'foo'] - user1538560

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接