Векторизованное решение:
Помните, что вы можете сравнить все элементы в b
со всеми элементами в a
, используя трансляцию:
b[:, None] > a
# array([[ True, False, False, False], # b[0] > a[:]
# [ True, True, False, False]]) # b[1] > a[:]
А теперь найдите индекс последнего True
значения в каждой строке, равный первому False
значению в каждой строке, минус 1
np.argmin((b[:, None] > a), axis=1) - 1
# array([0, 1])
Обратите внимание, что может быть неоднозначность относительно того, что означает возвращаемое значение -1
. Это может означать
b[x]
был больше, чем все элементы в a
или
b[x]
было не больше, чем любой элемент в a
В наших данных это означает
a = np.asarray([10, 20, 30, 40])
b = np.asarray([9, 12, 25, 39, 40, 41, 50])
mask = b[:, None] > a
# array([[False, False, False, False], # 9 is smaller than a[:], case 2
# [ True, False, False, False],
# [ True, False, False, False],
# [ True, True, True, False],
# [ True, True, True, False],
# [ True, True, True, True], # 41 is larger than a[:], case 1
# [ True, True, True, True]]) # 50 is larger than a[:], case 1
Так что для случая 1 нам нужно найти строки со всеми True
значениями:
is_max = np.all(mask, axis=1)
А для случая 2 нам нужно найти строки со всеми False
значениями:
none_found = np.all(~mask, axis=1)
Это означает, что мы можем использовать is_max
, чтобы найти и заменить все значения регистра 1 -1
положительным индексом
mask = b[:, None] > a
is_max = np.all(mask, axis=1)
# array([False, False, False, False, False, True, True])
idx = np.argmin(mask, axis=1) - 1
# array([-1, 0, 0, 2, 2, -1, -1])
idx[is_max] = len(a) - 1
# array([-1, 0, 0, 2, 2, 3, 3])
Однако следует помнить, что индекс -1
имеет значение : точно так же, как 3
, оно уже означает «последний элемент». Поэтому, если вы хотите использовать idx
для индексации, сохранение -1
в качестве маркера недопустимого значения может вызвать проблемы в будущем.