寻找多维 Python 数组的维度。

30
在Python中,是否可以编写一个函数来返回多维数组的维数(假设该数组的维度不是交错的)?
例如,[[2,3], [4,2], [3,2]] 的维数将是 [3, 2],而[[[3,2], [4,5]],[[3,4],[2,3]]] 的维数将是 [2,2,2]
Python是否有任何内置函数可以返回多维数组的所有维度,还是需要自己实现该函数?

3
第二个例子不是[2, 2, 2]吗? - DRC
3
出于好奇,它会在[[1,2],[3,4,5]]上做什么?或者[[1,2],[3,4],[5,[6,7]]] - Wrikken
1
@Wrikken 我的工作假设输入数组不会是锯齿状的。我想先检查数组维度的规则性,如果数组是锯齿状的,则抛出错误。 - Anderson Green
3
为什么这被标记为重复问题不明确:因为那个“重复”的问题是关于numpy数组的,而这个问题是关于Python列表的。那里的答案对OP没有帮助。 - eric
6个回答

46

不,没有内置的功能可以处理这种“数组”1,因为它可能是不规则的,而“维度”或“形状”的概念根本毫无意义。所以,你需要编写自己的代码。如果你可以做出沿着所有维度均匀分布的假设,那么可以按照以下步骤进行:

dim1 = len(a)
dim2 = len(a[0])
dim3 = len(a[0][0])
.
.
.

将其递归以处理所有维度非常容易。 这应该可以实现:

def dim(a):
    if not type(a) == list:
        return []
    return [len(a)] + dim(a[0])

但是如果你需要类似的东西,你可能需要考虑查看NumPy数组,它们具有numpy.ndarray.shape属性,可以给你提供你需要的结果。

from numpy import array
l = [[2, 3], [4, 2], [3, 2]]
a = array(l)
print a.shape

输出

(3, 2)

1 由于你并不是真正地看着数组,而是在看一个列表,或者是一个列表的列表,或者是一个列表的列表的列表,所以这里使用引号。


1
“维度”或“形状”的概念根本毫无意义。”不确定为什么您会这样说?这很有道理,您的回答也表明了这一点。Numpy优雅地处理了这种情况,尽管显然并不完全相同。看起来应该添加形状作为属性(不规则情况只需返回错误)。 - eric
Python 应该有一个这样的函数。 - user2585501

17
你可以使用numpy来完成它:

您可以使用numpy实现此操作:

import numpy
l = [[2,3], [4,2], [3,2]]
m = numpy.array(l)
print m.shape

但是你的第二个例子的形状是[2,2,2],而不是[1,4,5],除非我误解了你的问题...


是的,我指的是 [2,2,2] 而不是 [1,4,5]。 - Anderson Green
在Python 2中,“print m.shape”在语法上是有效的,但在Python 3中不再有效。 - Anderson Green
我现在经常使用numpy,关于列表的这些问题让我感到困惑。我该复习一下列表了吧? - eric
使用print(m.shape)来打印Python 3的形状。 - Sujay Phadke

7
那不是一个多维数组,它是一个列表。它恰好包含其他列表。并没有什么可以阻止你的列表成为:
[[2,3], [4,2], [3,2,4,5,6]]

在这种情况下,您期望这样的函数返回什么值?
没有一般的函数可以做到您所要求的,最主要的原因是Python本身没有定义矩阵/数组类。如果您愿意进行假设或编写断言来确保列表的统一性,则肯定可以编写自己的函数,该函数操作可迭代对象(如列表和元组)。对于第一维,请使用len(a),对于第二维,请使用len(a [0])等等。递归将成为您的朋友。
如果您对于矩阵使用了numpy数组,这实际上是很有意义的,那么您的函数将存在(它是ndarray类的shape属性)且具有意义。

Python中的数组和列表有什么区别吗?我以为它们是同义词。 - Anderson Green
当然,如果假定 OP 的数据确实有正则形状并提供非无回答的内容,或者询问澄清而不是假定,那么就会更有建设性。 - millimoose
1
@millimoose 我并没有对 OP 的数据做出任何假设。我只是试图解释为什么 Python 的设计者无法编写这样一个通用函数,因为他们不能做出这样的假设。 - David Heffernan
@AndersonGreen 更重要的是,Python没有(或者不常用)固定大小的内存块,您可以使用可能是多维索引来访问。列表确实在“幕后”使用可调整大小的数组。 - millimoose
1
@DavidHeffernan 我漏掉了原帖中关于特别询问内置函数的那一部分,因为它们以“是否可能编写…”开头。你是对的,因为提供这样一个内置函数没有意义,因为它需要考虑数据不规则的情况,这种通用性会为微小的好处带来太多的麻烦。(过度使用处理此类问题的库更好)。 - millimoose
显示剩余2条评论

5
假设输入的数组不是嵌套数组:
def arr_dimen(a):
  return [len(a)]+arr_dimen(a[0]) if(type(a) == list) else []

@millimoose在发布时重命名了函数,但在调用时忘记了重命名。感谢您指出这一点。 - Archit Jain

2

迭代方法

a = [[[3,2], [4,5]],[[3,4],[2,3]]]
shape = []
b = a
while type(b) == list:
    shape.append(len(b))
    b = b[0]
print(shape)

1
import numpy as np
# define array 3 row and 5 colums
a = np.arange(15).reshape(3, 5)
print ("the array elements:\n",a);
# print all dim 
print("all dim :\n",a.shape)
# the print the number of row only
print("the number of rows :\n",a.shape[0])
# the print the number of colume only
print("the number of cols :\n",a.shape[1])

enter image description here


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