Saya memiliki tantangan dalam JavaScript yang sedang saya coba cari tahu.
Pertimbangkan array ini:
let arr = [0, 1, 0, 2, 0, 3, 0, 4, 0, 5];
Saya harus menampilkan hasil ini:
arr = [0, 0, 0, 0, 0, 5, 4, 3, 2, 1]
Saya mengikuti garis logika ini untuk memposisikan nol di depan, menyesuaikan nilai indeks:
arr.sort((x, y) => {
if (x !== 0) {
return 1;
}
if (x === 0) {
return -1;
}
return y - x;
});
Tapi saya terjebak pada hasil ini:
arr = [0, 0, 0, 0, 0, 1, 2, 3, 4, 5]
Adakah yang punya tips bagaimana mengatasi ini?
javascript
arrays
sorting
lianbwl
sumber
sumber
return x - y;
?return y - x;
? Bahkan di javascript, saya tidak bisa memikirkan apa pun yang akan baik===0
atau!==0
.Jawaban:
Anda dapat mengurutkan berdasarkan delta
b
dana
(untuk penyortiran menurun) dan mengambilNumber.MAX_VALUE
, untuk nilai falsy seperti nol.Ini:
sama dengan nol.
sumber
NaN
jika keduanyaa
danb
nol. Ini mungkin perilaku yang tidak diinginkan.Array.prototype.sort
implementasi ditentukan jika komparator kembaliNaN
, jadi komparator ini adalah ide yang buruk. Itu mencoba untuk menjadi pintar, dan salah.Seperti yang dikatakan mdn docs:
Jika a dan b adalah dua elemen yang dibandingkan, maka:
Jadi, fungsi bandingkan memiliki bentuk berikut:
sumber
Jika Anda peduli efisiensi, mungkin yang tercepat adalah menyaring nol terlebih dahulu . Anda tidak ingin
sort
membuang waktu bahkan memandangnya, apalagi menambahkan kerja ekstra untuk callback perbandingan Anda untuk menangani kasus khusus itu.Terutama jika Anda mengharapkan angka nol yang signifikan, satu kali melewati data untuk memfilternya harus jauh lebih baik daripada melakukan jenis O (N log N) yang lebih besar yang akan melihat setiap nol beberapa kali.
Anda dapat dengan efisien menambahkan jumlah nol yang tepat setelah selesai.
Juga mudah untuk membaca kode yang dihasilkan. Saya menggunakan TypedArray karena efisien dan memudahkan pengurutan angka . Tetapi Anda dapat menggunakan teknik ini dengan Array biasa, menggunakan idiom standar
(a,b)=>a-b
untuk.sort
.Saya tidak tahu apakah TypedArray
.sort()
dan kemudian.reverse
lebih cepat daripada menggunakan fungsi perbandingan kustom untuk menyortir dalam urutan. Atau jika kita dapat menyalin dan membalikkan dengan cepat menggunakan iterator.Juga patut dipertimbangkan: hanya gunakan satu TypedArray dengan panjang penuh .
Alih-alih menggunakan
.filter
, loop di atasnya dan menukar nol ke depan array saat Anda pergi. Ini membutuhkan satu lewati data Anda.Kemudian gunakan
.subarray()
untuk mendapatkan tampilan TypedArray baru dari elemen non-nol dari ArrayBuffer yang mendasari yang sama. Pengurutan yang akan membuat Anda array penuh dengan awal nol dan ekor diurutkan, dengan pengurutan hanya pernah melihat elemen non-nol.Saya tidak melihat fungsi partisi dalam metode Array atau TypedArray, tapi saya hampir tidak tahu JavaScript. Dengan JIT yang baik, sebuah loop seharusnya tidak jauh lebih buruk daripada metode bawaan. (Terutama ketika metode itu melibatkan panggilan balik seperti
.filter
, dan kecuali jika menggunakan direalloc
bawah tenda untuk menyusut, ia harus mencari tahu berapa banyak memori yang dialokasikan sebelum benar-benar menyaring).Saya menggunakan Array biasa
.filter()
sebelum mengonversi ke TypedArray. Jika input Anda sudah menjadi TypedArray Anda tidak memiliki masalah ini, dan strategi ini menjadi lebih menarik.sumber
Cukup modifikasi kondisi fungsi perbandingan Anda seperti ini -
sumber
!a
masih benar. Ia akan kembali-1
a=b=0
Tidak bermain golf kode di sini:
sumber
Jangan menulis pengurutan angka Anda sendiri jika sudah ada. Apa yang ingin Anda lakukan adalah persis apa yang Anda katakan dalam judul; mengurutkan angka dalam urutan menurun kecuali nol di awal.
Jangan menulis kode apa pun yang Anda tidak perlu; Anda mungkin salah.
Pilih TypedArray berdasarkan pada Tipe nomor apa yang Anda inginkan untuk ditangani oleh Array. Float64 adalah default yang baik karena menangani semua nomor JS normal.
sumber
Array(n).fill(0)
.let f64arr = new Float64Array(arr.filter(n => n != 0))
, lalu[ ...Array(arr.length - f64arr.length).fill(0),
... jadi itu menambah 1 baris ekstra dan menyederhanakan baris terakhir.Anda dapat melakukan ini seperti ini:
atau Anda dapat melakukan ini:
sumber
sumber