Saya memiliki berikut ini untuk loop, dan ketika saya gunakan splice()
untuk menghapus item, saya kemudian mendapatkan bahwa 'detik' tidak terdefinisi. Saya dapat memeriksa apakah itu tidak terdefinisi, tetapi saya merasa mungkin ada cara yang lebih elegan untuk melakukan ini. Keinginannya adalah hanya menghapus item dan terus berjalan.
for (i = 0, len = Auction.auctions.length; i < len; i++) {
auction = Auction.auctions[i];
Auction.auctions[i]['seconds'] --;
if (auction.seconds < 0) {
Auction.auctions.splice(i, 1);
}
}
javascript
loops
dzm
sumber
sumber
Auction.auctions[i]['seconds']--
sebaliknyaauction.seconds--
?Jawaban:
Array sedang diindeks ulang ketika Anda melakukan
.splice()
, yang berarti Anda akan melewati indeks ketika satu dihapus, dan cache Anda.length
sudah usang.Untuk memperbaikinya, Anda harus mengurangi
i
setelah.splice()
, atau hanya mengulanginya secara terbalik ...Dengan cara ini pengindeksan ulang tidak mempengaruhi item berikutnya dalam iterasi, karena pengindeksan hanya mempengaruhi item dari titik saat ini ke akhir Array, dan item berikutnya dalam iterasi lebih rendah dari titik saat ini.
sumber
Ini adalah masalah yang cukup umum. Solusinya adalah mengulang ke belakang:
Tidak masalah jika Anda menghentikannya dari akhir karena indeks akan dipertahankan saat Anda mundur.
sumber
Hitung ulang panjang setiap kali melalui loop bukan hanya pada awalnya, misalnya:
Dengan begitu Anda tidak akan melampaui batas.
EDIT: menambahkan penurunan dalam pernyataan if.
sumber
Meskipun pertanyaan Anda adalah tentang menghapus elemen dari array yang di-iterasi dan bukan tentang menghilangkan elemen (selain beberapa pemrosesan lainnya) secara efisien, saya pikir kita harus mempertimbangkannya kembali jika dalam situasi yang sama.
Kompleksitas algoritmik dari pendekatan ini adalah
O(n^2)
sebagai fungsi splice dan for loop keduanya iterate atas array (fungsi splice menggeser semua elemen array dalam kasus terburuk). Sebagai gantinya Anda hanya bisa mendorong elemen yang diperlukan ke array baru dan kemudian hanya menetapkan array itu ke variabel yang diinginkan (yang baru saja diulangi).Karena ES2015 dapat kita gunakan
Array.prototype.filter
untuk menyesuaikan semuanya dalam satu baris:sumber
sumber
Jika Anda menggunakan ES6 + - mengapa tidak menggunakan metode Array.filter saja?
Perhatikan bahwa memodifikasi elemen array selama iterasi filter hanya berfungsi untuk objek dan tidak akan berfungsi untuk array nilai primitif.
sumber
Solusi sederhana lain untuk mencerna elemen array sekali:
sumber
Berikut adalah contoh lain untuk penggunaan sambungan yang tepat. Contoh ini akan menghapus 'atribut' dari 'array'.
sumber
Untuk setiap orang yang telah menjawab pertanyaan yang sangat mendasar ini dengan kode yang memiliki splice () dalam satu lingkaran, yang telah menjalankan waktu O (n 2 ), atau yang telah memutakhirkan jawaban seperti itu, selama tujuh tahun sejak pertanyaan ini diposting: Anda harus malu .
Berikut adalah solusi waktu linear sederhana untuk masalah waktu linear sederhana ini.
Ketika saya menjalankan cuplikan ini, dengan n = 1 juta, setiap panggilan untuk memfilterInPlace () membutuhkan 0,013 hingga 0,016 detik. Solusi kuadratik (mis. Jawaban yang diterima) akan membutuhkan jutaan kali lipat, atau lebih.
Perhatikan bahwa ini memodifikasi array asli di tempat daripada membuat array baru; melakukannya di tempat seperti ini bisa menguntungkan, misalnya dalam hal array adalah hambatan memori tunggal program; dalam hal ini, Anda tidak ingin membuat array lain dengan ukuran yang sama, bahkan untuk sementara.
sumber
Array.splice(i,1)
akan membuat contoh array baru setiap kali. Saya sangat malu.Sudah banyak jawaban indah di utas ini. Namun saya ingin berbagi pengalaman ketika saya mencoba menyelesaikan "menghapus elemen ke-n dari array" dalam konteks ES5.
Array JavaScript memiliki metode berbeda untuk menambah / menghapus elemen dari awal atau akhir. Ini adalah:
Pada dasarnya tidak ada metode di atas yang dapat digunakan secara langsung untuk menghapus elemen ke-n dari array.
Ini pada dasarnya membuat kita hanya memiliki satu metode array
Array.splice
untuk melakukan penghapusan elemen ke-n (ada hal-hal lain yang dapat Anda lakukan dengan metode ini juga, tetapi dalam konteks pertanyaan ini saya fokus pada penghapusan elemen):Berikut adalah kode yang disalin dari jawaban asli (dengan komentar):
Metode penting lainnya adalah
Array.slice
. Namun tipe pengembalian dari metode ini adalah elemen yang dihapus. Juga ini tidak mengubah array asli. Cuplikan kode yang dimodifikasi sebagai berikut:Karena itu, kita masih bisa menggunakan
Array.slice
untuk menghapus elemen n seperti yang ditunjukkan di bawah ini. Namun itu lebih banyak kode (karenanya tidak efisien)sumber
Cobalah untuk menyampaikan array ke newArray saat mengulang:
sumber
Dua contoh yang berhasil:
sumber
Cobalah ini
sumber
sumber
Anda bisa melihat dan menggunakannya
shift()
sumber