如果a是锯齿状的,而i是多维的,我们可以使用i来索引a:
In [78]: a = np.array([[10,0,30,10],[40,50,60,10],[70,80,90,10,30]])#NOTE:Jagged array
In [79]: i = np.array([[0,1],[0,2],[1,2]])
In [80]: a.shape # an array of list objects
Out[80]: (3,)
In [81]: a[i]
Out[81]:
array([[list([10, 0, 30, 10]), list([40, 50, 60, 10])],
[list([10, 0, 30, 10]), list([70, 80, 90, 10, 30])],
[list([40, 50, 60, 10]), list([70, 80, 90, 10, 30])]], dtype=object)
由于这些是列表对象,我们可以使用sum 来“连接”它们:
In [82]: a[i].sum(axis=1)
Out[82]:
array([list([10, 0, 30, 10, 40, 50, 60, 10]),
list([10, 0, 30, 10, 70, 80, 90, 10, 30]),
list([40, 50, 60, 10, 70, 80, 90, 10, 30])], dtype=object)
你的列表理解:
In [83]: e = [np.hstack(a[i[j]]) for j in range(len(i))]
In [84]: e
Out[84]:
[array([10, 0, 30, 10, 40, 50, 60, 10]),
array([10, 0, 30, 10, 70, 80, 90, 10, 30]),
array([40, 50, 60, 10, 70, 80, 90, 10, 30])]
一些时间安排:
In [85]: timeit a[i].sum(axis=1)
8.64 µs ± 17.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [86]: timeit e = [np.hstack(a[i[j]]) for j in range(len(i))]
63.3 µs ± 168 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
您的hstack 可能会更慢,因为它会将a 列表转换为数组。让我们绕过那个:
In [89]: [sum(a[i[j]],[]) for j in range(len(i))]
Out[89]:
[[10, 0, 30, 10, 40, 50, 60, 10],
[10, 0, 30, 10, 70, 80, 90, 10, 30],
[40, 50, 60, 10, 70, 80, 90, 10, 30]]
In [90]: timeit [sum(a[i[j]],[]) for j in range(len(i))]
8.41 µs ± 109 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
有时纯列表解决方案更快。转换数组列表需要时间。
===
如果两个数组都是均衡且多维的,我们可以使用纯“矢量化”解决方案:
In [104]: aa = np.array([[10,0,30,10],[40,50,60,10],[70,80,90,10]])
In [105]: i
Out[105]:
array([[0, 1],
[0, 2],
[1, 2]])
In [106]: aa[i]
Out[106]:
array([[[10, 0, 30, 10],
[40, 50, 60, 10]],
[[10, 0, 30, 10],
[70, 80, 90, 10]],
[[40, 50, 60, 10],
[70, 80, 90, 10]]])
In [107]: aa[i].reshape(3,-1)
Out[107]:
array([[10, 0, 30, 10, 40, 50, 60, 10],
[10, 0, 30, 10, 70, 80, 90, 10],
[40, 50, 60, 10, 70, 80, 90, 10]])
In [108]: timeit aa[i].reshape(3,-1)
5.07 µs ± 57.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
但是,一旦一个或多个数组/列表出现问题,您就会失去此选项,需要认真考虑列表替代方案。