Katakanlah saya memiliki array NumPy:
x = np.array([0, 1, 2, 0, 4, 5, 6, 7, 0, 0])
Pada setiap indeks, saya ingin mencari jarak ke nilai nol terdekat. Jika posisinya nol maka kembalikan nol sebagai jarak. Setelah itu, kami hanya tertarik pada jarak ke nol terdekat yaitu di sebelah kanan posisi saat ini. Pendekatan super naif akan seperti:
out = np.full(x.shape[0], x.shape[0]-1)
for i in range(x.shape[0]):
j = 0
while i + j < x.shape[0]:
if x[i+j] == 0:
break
j += 1
out[i] = j
Dan hasilnya adalah:
array([0, 2, 1, 0, 4, 3, 2, 1, 0, 0])
Saya memperhatikan pola hitung mundur / penurunan dalam output di antara nol. Jadi, saya mungkin bisa menggunakan lokasi nol (yaitu, zero_indices = np.argwhere(x == 0).flatten()
)
Apa cara tercepat untuk mendapatkan output yang diinginkan dalam waktu linier?
x.shape[0] - 1
)Jawaban:
Pendekatan # 1:
Searchsorted
untuk penyelamatan linear-waktu secara vektor (sebelum numba datang)!Pendekatan # 2: Lainnya dengan beberapa
cumsum
-Atau, langkah terakhir
cumsum
dapat diganti denganrepeat
fungsi -Pendekatan # 3: Lain-lain dengan hanya sebagian besar
cumsum
-sumber
Anda bisa bekerja dari sisi lain. Simpan penghitung pada berapa banyak digit bukan nol yang telah lewat dan tetapkan ke elemen dalam array. Jika Anda melihat 0, atur ulang penghitung ke 0
Sunting: jika tidak ada nol di sebelah kanan, maka Anda perlu memeriksa lagi
sumber
Anda dapat menggunakan perbedaan antara indeks dari setiap posisi dan jumlah kumulatif dari posisi nol untuk menentukan jarak ke nol sebelumnya. Ini bisa dilakukan maju dan mundur. Minimum antara jarak maju dan mundur ke nol sebelumnya (atau berikutnya) adalah yang terdekat:
hasil:
Kasus khusus di mana tidak ada nol hadir di tepi luar:
juga bekerja tanpa nol sama sekali
[EDIT] solusi non-numpy ...
jika Anda mencari solusi O (N) yang tidak membutuhkan numpy, Anda dapat menerapkan strategi ini menggunakan fungsi akumulasi dari itertools:
keluaran:
Jika Anda tidak ingin menggunakan pustaka apa pun, Anda dapat mengakumulasi jarak secara manual dalam satu lingkaran:
keluaran:
sumber
Intuisi pertama saya adalah menggunakan slicing. Jika x dapat berupa daftar normal alih-alih array numpy, maka Anda dapat menggunakannya
jika numpy diperlukan maka Anda bisa menggunakannya
tetapi ini kurang efisien karena Anda menemukan semua nol lokasi di sebelah kanan nilai dan kemudian menarik keluar hanya yang pertama. Hampir pasti cara yang lebih baik untuk melakukan ini di numpy.
sumber
Sunting: Saya minta maaf, saya salah paham. Ini akan memberi Anda jarak ke nol terdekat - mungkin di kiri atau kanan. Tetapi Anda dapat menggunakan
d_right
sebagai hasil antara. Ini tidak mencakup kasus tepi tidak memiliki nol di sebelah kanan sekalipun.sumber