有没有办法在一定深度创建多个嵌套列表?

Is there a way to create multiple nested lists to a certain depth?

提问人:kxrosene 提问时间:2/11/2023 最后编辑:kxrosene 更新时间:2/12/2023 访问量:164

问:

如果问题是间接的或令人困惑的,我深表歉意。我试图实现的是一个如下所示的列表:

[[[0,0],[0,0],[0,0]],[[0,0],[0,0],[0,0]],[[0,0],[0,0],[0,0]]]

但是,我希望列表具有可变数量的列表“深度”(上面列表的列表“深度”为 3,因为它在底部最多有 3 个列表;要访问其中的项目,它看起来像`aList[1][0][1]` )

我尝试使用列表推导:

aList = [[[[None for _ in range(3)] for _ in range(3)] for _ in range(3)] for _ in range(3)]

唯一的问题是,如果不直接编辑代码,我无法更改列表的深度。

我能做些什么来达到我想要的结果?(我试图实现的列表包含 7^4 (2401) 个项目,只是为了让您知道。

python python-3.x 嵌套列表 numpy

评论

0赞 wim 2/11/2023
列表理解将很快变得难以理解。对于递归函数来说,这听起来像是一份不错的工作..
0赞 Kelly Bundy 2/11/2023
列表的大小是相同的还是不同的?
0赞 kxrosene 2/11/2023
@KellyBundy不同的尺寸。列表的宽度和深度必须是可变的。
0赞 Kelly Bundy 2/11/2023
嗯,这不清楚。第一个示例中列表的宽度和深度是多少?(一个)。[[[0,0], ...
0赞 kxrosene 2/11/2023
@KellyBundy深度为 3,每个级别的宽度都不同。第一个 3 个,下一个 3 个,最后一个 2 个。

答:

2赞 Tom McLean 2/11/2023 #1

递归是你的朋友:

def nested_list(depth, size):
    if depth == 1:
        return [None for _ in range(size)]
    return [nested_list(depth-1, size) for _ in range(size)]

评论

0赞 Kelly Bundy 2/11/2023
无法生成它们的第一个示例,因为它们的大小并不完全相同。
3赞 mozway 2/11/2023 #2

对于来说,这可能是一份不错的工作:

import numpy as np

out = np.zeros((3, 3, 2), dtype=int).tolist()

输出:

[[[0, 0], [0, 0], [0, 0]],
 [[0, 0], [0, 0], [0, 0]], 
 [[0, 0], [0, 0], [0, 0]]]

或者使用递归函数:

def nested(shape):
    if shape:
        n, *shape = shape
        return [nested(shape) for _ in range(n)]
    return 0

out = nested((3, 3, 2))

评论

0赞 kxrosene 2/11/2023
只是为了确认,我可以将 (3, 3, 2) 作为元组传入?
0赞 mozway 2/11/2023
@iCxbe yes 应该是一个元组(或可迭代)shape
0赞 Dorian Turba 2/11/2023 #3

纯python解决方案

我的建议:只有当你不能使用 numpy 时。

递归

警告,此代码很简单,但根据您的配置有深度限制。

from pprint import pprint


def list_in_depth_recursive(depth: int, length: int | None = None):
    """limited by stack size (default 500 or 1000)"""
    if length is None:
        length = depth

    if depth <= 1:
        return [None] * length

    return [list_in_depth_recursive(depth - 1, length) for _ in range(length)]


pprint(list_in_depth_recursive(3))
# [[[None, None, None], [None, None, None], [None, None, None]],
#  [[None, None, None], [None, None, None], [None, None, None]],
#  [[None, None, None], [None, None, None], [None, None, None]]]
>>> pprint(list_in_depth_recursive(10000))
RecursionError: maximum recursion depth exceeded in comparison

迭 代

警告,由于 ,您还可以使用此代码生成 。deepcopyRecursionError

from copy import deepcopy
from pprint import pprint


def list_in_dept_iterative(depth: int, length: int | None = None):
    """limited by memory"""
    if length is None:
        length = depth

    if depth <= 0:
        return [None]

    current_depth_list = [None] * length
    while depth > 1:
        current_depth_list = [deepcopy(current_depth_list) for _ in range(length)]
        depth -= 1
    return current_depth_list


pprint(list_in_dept_iterative(3))
# [[[None, None, None], [None, None, None], [None, None, None]],
#  [[None, None, None], [None, None, None], [None, None, None]],
#  [[None, None, None], [None, None, None], [None, None, None]]]

评论

0赞 kxrosene 2/11/2023
我之后的列表实际上很大(7^4 = 2401),所以我不确定递归是否可以接受。谢谢你。
0赞 Kelly Bundy 2/11/2023
@iCxbe嗯?你的意思是 7×7×7×7,就像你的第一个例子是 3×3×2 一样吗?那么这不是“相当大的”,而是非常的,没有一个解决方案会有丝毫问题。你是说别的吗?
0赞 Dorian Turba 2/12/2023
list_in_depth_recursive(4, 7) 不是问题。如果您只需要 500 或 1000+ 的深度。list_in_depth_recursive(1000) 通常是极限,所以一个更大的列表,1000^1000。
0赞 kxrosene 2/13/2023
@DorianTurba哦,好吧,这只是我不明白这个问题的一个例子。感谢您的澄清。
0赞 cards 2/11/2023 #4

一种递归方法reduce

from functools import reduce

shape = 3, 2, 5
lst = reduce(lambda row, dim: row + [[0] * dim], shape, [])
#[[0, 0, 0], [0, 0], [0, 0, 0, 0, 0]]
-2赞 Kelly Bundy 2/11/2023 #5

如果我们通过字符串进行重复数据删除,我们可以乘以:

a = eval(str([[[0]*2]*3]*3))

对于可变尺寸,例如:sizes = 2, 3, 3

n = len(sizes)
a = eval(str(eval('[' * n + '0' + ']*%d' * n % sizes)))

在线试用!

评论

0赞 kxrosene 2/11/2023
我认为这样做的问题在于这些值都指向相同的区域,因此当我尝试更改单个值时,多个值会同时更改,这不是我所追求的。
0赞 Kelly Bundy 2/11/2023
@iCxbe 这不是真的。重复数据删除解决了这个问题。重复数据删除代码也很难被忽视,我在文中明确指出了这一点。
0赞 kxrosene 2/11/2023
不过,还有另一个问题。如果我希望通过更改单个变量来更改深度,该怎么办?它有一个固定的深度,如果不直接编辑代码本身,就不容易改变它。如果可能的话,请提供解决方案,因为我确实指定了深度必须是可变的。
0赞 Kelly Bundy 2/11/2023
@iCxbe啊,是的,这是一个真正的问题。我实际上从一个可变版本开始,然后显然忘记了这一点。昨晚很晚了。我将添加一个变量。
0赞 Alain T. 2/12/2023 #6

递归可能是你最好的选择:

def matrix(size,*more):
    return [matrix(*more) for _ in range(size)] if more else [0]*size

输出:

matrix(3,3,2)

[[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]

您还可以通过拆分初始 1D 列表以针对每个维度进行细分来迭代执行此操作:

def matrix(*dims):
    result = [0]
    for d in dims: result *= d
    for d in dims[:0:-1]:
        result = [ result[i:i+d] for i in range(0,len(result),d) ]
    return result