以简洁且可扩展的方式表达多个数组元素的每个组合的链式不等式

Expressing chained inequality for each combination of elements of multiple arrays in a concise and scalable way

我有三个不同大小的一维数组 a, b, c,我想为每个组合 x in a, y in b, z in c 计算链式不等式 x < y < z。例如:

import numpy as np

a = np.random.randint(100, size=100)
b = np.random.randint(100, size=200)
c = np.random.randint(100, size=300)

expected = np.empty(shape=(a.size, b.size, c.size), dtype=bool)
for i, x in enumerate(a):
    for j, y in enumerate(b):
        for k, z in enumerate(c):
            expected[i, j, k] = x < y < z

上面的三重循环是为了展示预期结果应该如何出现,但我当然想使用向量化语句。为此,我想出了以下两个表达式:

result1 = (a[:, None] < b)[:, :, None] & (b[:, None] < c)[None, :, :]
result2 = (a[:, None, None] < b[:, None]) & (b[None, :, None] < c[None, :])

两者都涉及大量的重塑和插入额外的维度,并不是很明显或表现力很强。我觉得应该有一种更简洁的方法来实现这一点,我一直在研究 np.ufunc.outer 但我无法弄清楚如何将它用于此目的,因为在执行 & 这两个操作数应该共享一个轴。

缩放到任意数量的数组:作为一个附加问题,我想问一下是否有一种简洁的方法可以将上述操作缩放到任意数量的一维数组数组,例如每个元素组合的 a < b < c < d < ... < g,例如给出了 arrays.

的列表

np.ix_这里方便:

A,B,C = np.ix_(a,b,c)
(A<B)&(B<C)

任意数量的数组:

l = [np.random.randint(10*i, size=i) for i in range(2,6)]
L = np.ix_(*l)
np.bitwise_and.reduce(list(map(np.less, L, L[1:])))

或使用functools(快一点)

import functools as ft
ft.reduce(np.bitwise_and, map(np.less, L, L[1:]))