在python中自动增长2D列表?

时间:2014-03-16 11:49:11

标签: python list python-3.x

阅读Automatically growing lists in Python后,我现在正在尝试创建一个自动增长的二维列表。 基本上我会说

>>> l = 2DGrowingList(' ') # Fills the inner lists with space (' ') character
>>> l[1][2] = 'x'
>>> print(l)
[[], [' ', ' ', 'x']]
>>> l[0][1] = 'a'
>>> print(l)
[[' ', 'a'], [' ', ' ', 'x']]

我的尝试是这样的:

class GrowingList(list):

    def __init__(self, fill):
        super().__init__()
        self.fill = fill

    def __setitem__(self, index, value):
        if index > len(self) - 1:
            self.extend([self.fill] * (index + 1 - len(self)))
        list.__setitem__(self, index, value)

现在我尝试创建一个新的2D列表:

l = GrowingList(GrowingList(' '))

但它并没有像预期的那样工作,因为它使用相同的实例来填充列表:

>>> l[3][0] = 'x'
>>> print(l)
[[], [], [], ['x']]
>>> l[1][0] = 'y'
>>> print(l)
[['y'], ['y'], ['y'], 'x']

此外,它不允许我立即使用l[0][2] = ...,但我必须先致电l[0]才能访问l[0][2]

2 个答案:

答案 0 :(得分:0)

可以通过更改类来使用工厂函数而不是填充值来解决此问题。但是如果你想直接进行二维索引,而不直接在外部列表中设置任何内容,除了__getitem__之外,你还需要__setitem__扩展列表。这是因为l[x][y]在设置l[x]索引之前首先尝试获取y

更好的方法可能是使用具有row, column元组的键的字典。您可以使用dict.get检查值并获取缺失密钥的默认值。

l = {}
l[3, 5] = "x"
l[0, 0] = "y"
l[9, 9] = "z"
for i in range(10):
    print("".join(l.get((i, j), ".") for j in range(10))) # "." is default value

打印:

y.........
..........
..........
.....x....
..........
..........
..........
..........
..........
.........z

答案 1 :(得分:0)

对于您的问题,最简单的解决方案可能是使用可调用的tu构建填充值,以便在矩阵中包含不同的实例。

    class GrowingList(list):

    def __init__(self, fill):
        super().__init__()
        self.fill = fill

    def __setitem__(self, index, value):
        if index > len(self) - 1:
            self.extend(self.fill() for i in range(index + 1 - len(self)))
        list.__setitem__(self, index, value)

请注意,fill现在是可调用的,因此您需要将其包装在函数中:

l = GrowingList(lambda: GrowingList(lambda: ' '))

您也不能依赖项目乘法习惯用法,因为它只重复值 n 次。为避免这种情况,使用列表推导。

但这种方法仍存在问题:

l = GrowingList(lambda: GrowingList(lambda: ' '))
l[1][3] = 1

IndexError: list index out of range

您可能需要考虑使用Blckknght建议的分散矩阵字典。