首先让我们专注于做(不要担心“循环”):
In [82]: duplicates = [np.array([0,3]), np.array([3,0]), np.array([6,7,8])]
In [83]: [labels[x] for x in duplicates]
Out[83]: [array([2, 3]), array([3, 2]), array([0, 0, 0])]
我将duplicates 设为列表,而不是数组。 dtype 对象的一维数组只不过是一个列表。 (但两者都适用)
(np.concatenate(duplicates) 解决方案移至末尾)
只要您的 duplicates 元素的长度不同,就没有办法(我能想到的)避免“循环”,即对这些元素进行迭代。这就是numpy 索引的本质。二维操作本质上是“矩形的”。如果有一个函数直接执行它,它可能隐藏了一个循环。
如果只有少数duplicates 更长,并且您不介意丢失“额外”值,则可以剪掉它们:
labels[np.array([x[:2] for x in duplicates])]
array([[2, 3],
[3, 2],
[0, 0]])
同样,您可以将每个 duplicate 扩展为相同的长度。有一个通用的np.pad 函数,但它可能提供比您需要的更多的选项。
对于填充,目标长度需要理解,就像填充本身一样。 np.pad 可用于复制最后一个值。另一种选择是一些默认或虚拟索引(例如0)。
mlen = max([len(x) for x in duplicates])
padded_dups = [np.pad(x,(0,mlen-len(x)),'edge') for x in duplicates]
labels[np.array(padded_dup)]
array([[2, 3, 3],
[3, 2, 2],
[0, 0, 0]])
duplicates 应该是列表还是对象数组?可能没多大关系。
[labels[x] for x in np.array(duplicates)]
有效。正如您所注意到的,np.array(duplicates)-1 有效,而列表需要[x-1 for x in duplicates]。
在初步计时中,两个减法大约花费相同的时间,这意味着对象数组减法正在执行等效的列表推导。
这样的数组有时表现得像一个列表,而在其他情况下又像一个二维数组。这是一个正在发展的领域,因此您必须逐个尝试。
array([array([0, 3]), array([3, 0]), array([6, 7, 8])], dtype=object)
之前我展示了您可以轻松获得标签的平面列表:
flat_labels = labels[np.concatenate(duplicates)]
# array([2, 3, 3, 2, 0, 0, 0])
我刚刚意识到np.split 很容易将这样的数组拆分为您想要的子数组:
split_indices = np.cumsum([len(x) for x in duplicates])[:-1]
np.split(flat_labels,split_indices)
# [array([2, 3]), array([3, 2]), array([0, 0, 0])]