Вот векторизация, работающая от a
. Идея состоит в том, чтобы умножить каждый столбец на 10**seq
, seq
- число до числа столбцов и в порядке убывания. Это будет действовать как объединение цифр вдоль столбцов, как только мы возьмем sum
вдоль второй оси. Наконец, мы можем повернуть процесс вспять, применив ту же логику c, но вместо этого разделив ее и передав в результирующую форму после умножения на 1.1
, и взяв по модулю 10 результата, чтобы сохранить только последний ди git:
s = np.arange(a.shape[1]-1, -1, -1, dtype=np.float64)
# concat digits along cols, and multiply
b = (a * 10**s).sum(1)*1.1
# highest amount of digits in b
n_cols = int(np.log10(b.max()))
# broadcast division to reverse
c = b[:, None] // 10**np.arange(n_cols, -1, -1, dtype=np.float64)
# keep only last digit
c1 = (c%10).astype(int)
print(c1)
array([[0, 1, 2, 1],
[0, 2, 0, 9],
[0, 1, 1, 0],
[1, 0, 0, 1],
[1, 0, 8, 9],
[0, 9, 9, 0]])
Обновление -
Приведенный выше подход работает для целых чисел, не превышающих поддерживаемых для int64
, а именно:
np.iinfo(np.int64).max
# 9223372036854775807
Однако в таких случаях можно сделать, чтобы сохранить значения массивов как python int
, а не numpy dtype
. Таким образом, мы могли бы определить np.arange
как объект dtype
, и вышеприведенное должно работать для общего примера:
s = np.arange(a.shape[1]-1, -1, -1, dtype=object)
# concat digits along cols, and multiply
b = (a * 10**s).sum(1)*1.1
# highest amount of digits in b
n_cols = int(np.log10(b.max()))
# broadcast division to reverse
c = b[:, None] // 10**np.arange(n_cols, -1, -1, dtype=object)
# keep only last digit
c1 = (c%10).astype(int)