Адаптировано с https://stackoverflow.com/a/49445693/7207392
import numpy as np
import operator as op
import itertools as it
def cartesian_product_pp(arrays, out=None):
la = len(arrays)
h, w = zip(*map(op.attrgetter('shape'), arrays))
w = np.fromiter(it.chain([0], w), int, la+ 1)
W = w.cumsum()
h = *h, W[la]
dtype = np.result_type(*arrays)
arr = np.empty(h, dtype=dtype)
arrs = *it.accumulate(it.chain((arr,), it.repeat(0, la-1)), np.ndarray.__getitem__),
idx = slice(None), *it.repeat(None, la-1)
for i in range(la-1, 0, -1):
arrs[i][..., W[i]:W[i+1]] = arrays[i][idx[:la-i]]
arrs[i-1][1:] = arrs[i]
arr[..., W[0]:W[1]] = arrays[0][idx]
return arr.reshape(-1, W[la])
# example
a = np.r_[:3].reshape(1, 3)
b = np.r_[5:20].reshape(3, 5)
c = np.r_[17:38].reshape(3, 7)
p = cartesian_product_pp([a, b, c])
Выход:
>>> p
array([[ 0, 1, 2, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23],
[ 0, 1, 2, 5, 6, 7, 8, 9, 24, 25, 26, 27, 28, 29, 30],
[ 0, 1, 2, 5, 6, 7, 8, 9, 31, 32, 33, 34, 35, 36, 37],
[ 0, 1, 2, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23],
[ 0, 1, 2, 10, 11, 12, 13, 14, 24, 25, 26, 27, 28, 29, 30],
[ 0, 1, 2, 10, 11, 12, 13, 14, 31, 32, 33, 34, 35, 36, 37],
[ 0, 1, 2, 15, 16, 17, 18, 19, 17, 18, 19, 20, 21, 22, 23],
[ 0, 1, 2, 15, 16, 17, 18, 19, 24, 25, 26, 27, 28, 29, 30],
[ 0, 1, 2, 15, 16, 17, 18, 19, 31, 32, 33, 34, 35, 36, 37]])
Время для этого, подходы @ B.M. и @ Bazingaa:
>>> timeit(lambda: cartesian_product_pp([a,b,c]), number=1000)*1000
15.173833002336323
>>> timeit(lambda: combine([a,b,c]), number=1000)*1000
31.1394709860906
>>> timeit(lambda: np.array([np.hstack((i, j, k)) for i in a for j in b for k in c]), number=1000)*1000
51.15771805867553