【发布时间】:2020-09-11 08:38:09
【问题描述】:
我正在寻找一种有效的方法来检查数组是否是锯齿状的,其中“锯齿状”意味着数组中的一个元素与它在同一维度上的相邻元素具有不同的形状。
例如[[1, 2], [3, 4, 5]] 或 [[1, 2], [3, 4], [5, 6], [[7], [8]]]
为方便起见,我使用列表语法,但参数可能是嵌套列表或嵌套的 numpy 数组。为了方便起见,我还显示了整数,最低级别的组件可以是任何东西(例如通用对象)。假设最低级别的对象本身不可迭代(例如str 或dict,但对于能够处理这些问题的解决方案来说绝对是加分!)。
尝试:
递归地展平一个数组非常容易,虽然我猜in效率很高,然后展平后的数组的长度可以与输入数组的numpy.size 进行比较。如果它们匹配,则它不是锯齿状的。
def really1d(arr):
# Returns false if the given array is not 1D or is a jagged 1D array.
if np.ndim(arr) != 1:
return False
if len(arr) == 0:
return True
if np.any(np.vectorize(np.ndim)(arr)):
return False
return True
def flatten(arr):
# Convert the given array to 1D (even if jagged)
if (not np.iterable(arr)) or really1d(arr):
return arr
return np.concatenate([flatten(aa) for aa in arr])
def isjagged(arr):
if (np.size(arr) == len(flatten(arr))):
return False
return True
我很确定串联会复制所有数据,这完全是浪费。也许有一个itertools 或numpy.flatiter 实现相同目标的方法?最终,扁平化数组仅用于查找它的长度。
【问题讨论】:
-
这个答案在 java 中,但它可能会有所帮助。 stackoverflow.com/a/22874074/13314450
-
感谢@LD,我确实看到了一些其他语言的答案,但我怀疑找到一个有效的答案需要使用适当的
numpy或itertools方法来不必要地复制数据,我想我在这里的尝试中正在这样做。 -
你显示的是列表,但测试都使用
numpy。一个“锯齿状”的 numpy 数组将具有objectdtype。通常形状也是 1d(或至少比预期的维度少)。 -
@hpaulj 列表为简单起见显示,问题已修正。如果我一般都知道“预期”的形状,那么解决方案将是微不足道的。
-
鉴于您的问题有多普遍,我不确定效率是否可以衡量。您要么有一个列表列表,要么有一个对象 dtype 数组(数字 dtype 不能参差不齐。对象数组的迭代比列表的迭代慢。快速编译的 numpy 方法在对象数组中不起作用。跨度>