如何在不使用 numpy 的情况下获得列表形状?

Yih*_*uan 15 python python-3.x

a1=[1,2,3,4,5,6]  
b1=[[1,2,3], [4,5,6]]
Run Code Online (Sandbox Code Playgroud)

如果使用np.shapelista1将返回(6,)并且b1将返回(2, 3).

如果禁止使用 Numpy,我如何获得 list 的形状a1

我主要对如何让python程序知道a1只有一维感到困惑。有什么好的方法吗?

小智 21

>>>a = [1,2,3,4,5,6]
>>>print (len(a))
6
Run Code Online (Sandbox Code Playgroud)

对于一维列表,可以使用上述方法。len(list_name) 返回列表中的元素数。

>>>a = [[1,2,3],[4,5,6]]
>>>nrow = len(a)
>>>ncol = len(a[0])
>>>nrow
2
>>>ncol
3
Run Code Online (Sandbox Code Playgroud)

上面给出了列表的维度。len(a) 返回行数。len(a[0]) 返回 a[0] 中的行数,即列数。

这是原始答案的链接


Reg*_*hew 11

该问题明确指出“不使用 numpy”。但是,如果有人到达这里寻找无条件的解决方案,请考虑以下内容。该解决方案适用于平衡列表。

b1=[[1,2,3], [4,5,6]]
np.asarray(b1).shape
Run Code Online (Sandbox Code Playgroud)

(2, 3)

  • 仅供参考,“从不规则的嵌套序列创建 ndarray ...已被弃用。” (3认同)

hir*_*ist 6

这是解决您的问题的递归尝试。只有在相同深度的所有列表都具有相同的长度时,它才会起作用。否则它会引发一个ValueError

from collections.abc import Sequence


def get_shape(lst, shape=()):
    """
    returns the shape of nested lists similarly to numpy's shape.

    :param lst: the nested list
    :param shape: the shape up to the current recursion depth
    :return: the shape including the current depth
            (finally this will be the full depth)
    """

    if not isinstance(lst, Sequence):
        # base case
        return shape

    # peek ahead and assure all lists in the next depth
    # have the same length
    if isinstance(lst[0], Sequence):
        l = len(lst[0])
        if not all(len(item) == l for item in lst):
            msg = 'not all lists have the same length'
            raise ValueError(msg)

    shape += (len(lst), )
    
    # recurse
    shape = get_shape(lst[0], shape)

    return shape
Run Code Online (Sandbox Code Playgroud)

鉴于您的输入(以及来自评论的输入),这些是结果:

a1=[1,2,3,4,5,6]
b1=[[1,2,3],[4,5,6]]

print(get_shape(a1))  # (6,)
print(get_shape(b1))  # (2, 3)
print(get_shape([[0,1], [2,3,4]]))  # raises ValueError
print(get_shape([[[1,2],[3,4]],[[5,6],[7,8]]]))  # (2, 2, 2)
Run Code Online (Sandbox Code Playgroud)

不确定最后的结果是否是您想要的。


更新

正如mkl在评论中指出的那样,上面的代码不会捕获嵌套列表形状不一致的所有情况;例如[[0, 1], [2, [3, 4]]]不会引发错误。

这是检查形状是否一致的一个镜头(可能有更有效的方法来做到这一点......)

from collections.abc import Sequence, Iterator
from itertools import tee, chain

def is_shape_consistent(lst: Iterator):
    """
    check if all the elements of a nested list have the same
    shape.

    first check the 'top level' of the given lst, then flatten
    it by one level and recursively check that.

    :param lst:
    :return:
    """

    lst0, lst1 = tee(lst, 2)

    try:
        item0 = next(lst0)
    except StopIteration:
        return True
    is_seq = isinstance(item0, Sequence)

    if not all(is_seq == isinstance(item, Sequence) for item in lst0):
        return False

    if not is_seq:
        return True

    return is_shape_consistent(chain(*lst1))
Run Code Online (Sandbox Code Playgroud)

可以这样使用:

lst0 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
lst1 = [[0, 1, 2], [3, [4, 5]], [7, [8, 9]]]

assert is_shape_consistent(iter(lst0))
assert not is_shape_consistent(iter(lst1))
Run Code Online (Sandbox Code Playgroud)