索引和切片多维列表



假设我有一个嵌套列表(ndlist),类似于任意维度的N-D数组(设ndim维数)和一个带有len(indexes) == ndim的元组indexes。如果ndlist是 N-D 数组,我可以执行以下操作:

ndlist[indexes] = (some object)

列表的等效项是什么?请注意,ndim是任意的,所以我不能像这样硬编码:

ndlist[indexes[0]][indexes[1]]... = (some object)

下面是ndim == 3的示例:

ndlist = [[[10, 10], [10, 10]],[[10, 10],[10,10]]] % 所有元素等于 10 的三维 (2x2x2) 列表

当我事先知道ndim时,我可以像这样编辑 ndlist 的 (0,0,0) 元素:

ndlist[0][0][0] =11%从 10 更改为 11 需要按顺序排列 3 个 [0]

现在假设 ndims == 4(4 维列表)。编辑 ndlist 的 (0,0,0,0) 元素需要这样的东西:

ndlist[0][0][0][0] =11%更改为 11 需要按顺序排列 4 个 [0]

对于任意 ndim:

ndlist[0][0][0]...[0] =11%更改为 11 需要按顺序执行 NDIM [0]

如您所见,对于事先不知道 ndim 的一般情况,我无法以这种方式索引列表,因为它需要键入与 ndim 一样多的 [0]。

如果我有一个这样的数组,而不是列表:

ndarray = np.array(ndlist)

访问 (0, 0, 0, ...,0) 不会有问题,因为我可以使用元组同时索引所有维度,如下所示:

% 3D 案例

索引 = (0,0,0)

ndarray[indexes]

% 4D 案例

索引 = (0,0,0,0)

ndarray[indexes]

% n-d 案例

索引 = (0, 0, 0, ... ,0) % 我可以用代码生成这个

ndarray[索引] = 11

有没有办法用这样的单个元组索引列表?更好的是,元组可以保存切片而不是索引吗?对于实例数组还允许这样做:

ndarray[0:2, 0, 0] = np.array([0, 0])


发现我的问题的唯一解决方案是使用递归一次索引一个维度。有没有更好的解决方案?谢谢!

现在我明白了这个问题。如果您愿意有一个功能为您执行此操作,那将很容易。否则,您需要创建自己的列表类型。

功能

您将需要一个函数来获取列表并n(未知)数量的元素。n意味着您将需要*argv

该函数将获取列表并获取n(argv)中的第i个元素。

def get_element(the_list, *argv):
sub_list = the_list.copy()
for i in argv:
sub_list = sub_list[i]
return sub_list

注意:该函数会复制原始list以确保其未更改。

注意:您还需要处理index out of range错误。现在它会引发一个错误TypeError: 'blabla' object is not subscriptable.

您自己的列表类型

在这里,您将创建一个具有任何名称的类(让我们坐TypedList),该类继承自list并覆盖__getitem__方法。

class TypedList(list):
def __getitem__(self, keys):
sub_list = self.copy()
for i in keys:
sub_list = sub_list[i]
return sub_list

if __name__ == '__main__':
ndlist = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
lst = TypedList(ndlist)
print(lst[1, 1, 0])

在这里,您还需要处理index out of range错误。

评论后编辑。

你说得很对,我实际上没有回答这个问题。既然你已经接受了我的回答,我就想办法去做。

一些编辑

我的实现有一个小(实际上是巨大的)问题。如果仅使用整数作为索引,它将失败。因此,代码必须更改为:

class TypedList(list):
def __getitem__(self, keys):
sub_list = self.copy()
if isinstance(keys, int):
return sub_list[keys]
for i in keys:
sub_list = sub_list[i]
return sub_list

现在。我必须澄清

Python 永远不会复制你在函数调用期间传递的对象。

那是什么意思?如果将传递的对象修改为函数,则对象本身将更改。请注意,我是如何先复制列表,然后再处理列表的。请参阅:https://stackoverflow.com/a/575337/2681662

我们将通过编写一个实际修改传递对象的函数来利用这一点:

def set_value(the_list, keys, value):
for i in range(len(keys) - 1):
the_list = the_list[keys[i]]
the_list[keys[-1]] = value

现在唯一要做的就是,以某种方式设法使这个函数成为我们类的方法并从__setitem__使用它

class TypedList(list):
def __set(self, the_list, keys, value):
for i in range(len(keys) - 1):
the_list = the_list[keys[i]]
the_list[keys[-1]] = value
def __setitem__(self, keys, value):
if isinstance(keys, int):
super().__setitem__(keys, value) # <- This has to be done. Otherwise maximum recursion depth would occurre...
else:
self.__set(self, keys, value)
def __getitem__(self, keys):
sub_list = self.copy()
if isinstance(keys, int):
return sub_list[keys]
for i in keys:
sub_list = sub_list[i]
return sub_list

if __name__ == '__main__':
ndlist = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
lst = TypedList(ndlist)
lst[1, 1, 0] = 22
print(lst)

这里我们有一个名为__set的私有方法,__setitem__会调用它来修改self这是一种list

最新更新