Saya ingin menghitung melalui array di Swift, dan menghapus item tertentu. Saya bertanya-tanya apakah ini aman untuk dilakukan, dan jika tidak, bagaimana saya bisa mencapai ini.
Saat ini, saya akan melakukan ini:
for (index, aString: String) in enumerate(array) {
//Some of the strings...
array.removeAtIndex(index)
}
ios
arrays
swift
enumeration
Andrew
sumber
sumber
filter
mengembalikan array baru. Anda tidak menghapus apa pun dari larik. Saya bahkan tidak akan memanggilfilter
pencacahan. Selalu ada lebih dari satu cara untuk menguliti kucing.Anda mungkin mempertimbangkan
filter
cara:var theStrings = ["foo", "bar", "zxy"] // Filter only strings that begins with "b" theStrings = theStrings.filter { $0.hasPrefix("b") }
Parameter dari
filter
hanyalah sebuah closure yang mengambil sebuah instance tipe array (dalam hal iniString
) dan mengembalikan aBool
. Ketika hasilnya adalahtrue
itu menyimpan elemen, jika tidak, elemen akan disaring.sumber
filter
tidak memperbarui array, itu hanya mengembalikan yang barufilter
metode menjadimutating
satu kemudian (karena saya telah membacamutating
kata kunci memungkinkan fungsi seperti ini untuk mengubahself
sebagai gantinya)?Array
menandainya sebagaimutating
dan mirip dengan kode pertanyaan. Bagaimanapun pertimbangkan bahwa ini mungkin tidak selalu menjadi keuntungan. Bagaimanapun setiap kali Anda menghapus objek, array Anda mungkin diatur ulang dalam memori. Dengan demikian dapat lebih efisien mengalokasikan larik baru dan kemudian membuat substitusi atom dengan hasil fungsi filter. Kompilator dapat melakukan lebih banyak pengoptimalan, bergantung pada kode Anda.Di Swift 3 dan 4 , ini akan menjadi:
Dengan angka, menurut jawaban Johnston:
var a = [1,2,3,4,5,6] for (i,num) in a.enumerated().reversed() { a.remove(at: i) } print(a)
Dengan string sebagai pertanyaan OP:
var b = ["a", "b", "c", "d", "e", "f"] for (i,str) in b.enumerated().reversed() { if str == "c" { b.remove(at: i) } } print(b)
Namun, sekarang di Swift 4.2 atau yang lebih baru, ada cara yang lebih baik dan lebih cepat yang direkomendasikan oleh Apple di WWDC2018:
var c = ["a", "b", "c", "d", "e", "f"] c.removeAll(where: {$0 == "c"}) print(c)
Cara baru ini memiliki beberapa keunggulan:
filter
.sumber
{$0 === Class.self}
tidak berfungsiKetika sebuah elemen pada indeks tertentu dihapus dari sebuah array, semua elemen berikutnya akan mengalami perubahan posisi (dan indeks), karena mereka bergeser mundur satu posisi.
Jadi cara terbaik adalah menavigasi array dalam urutan terbalik - dan dalam hal ini saya sarankan menggunakan for loop tradisional:
for var index = array.count - 1; index >= 0; --index { if condition { array.removeAtIndex(index) } }
Namun menurut saya pendekatan terbaik adalah dengan menggunakan
filter
metode tersebut, seperti yang dijelaskan oleh @perlfly dalam jawabannya.sumber
Tidak, tidak aman untuk mengubah array selama enumaration, kode Anda akan macet.
Jika Anda ingin menghapus hanya beberapa objek, Anda dapat menggunakan
filter
fungsi tersebut.sumber
filter
ini lebih aman . Inilah contoh bodoh saya:var y = [1, 2, 3, 4, 5]; print(y); for (index, value) in y.enumerated() { y.remove(at: index) } print(y)
Buatlah larik yang bisa berubah untuk menyimpan item yang akan dihapus dan kemudian, setelah pencacahan, hapus item tersebut dari aslinya. Atau, buat salinan dari array (tidak dapat diubah), menghitung itu dan menghapus objek (bukan dengan indeks) dari aslinya saat menghitung.
sumber
Perulangan for tradisional dapat diganti dengan perulangan while sederhana, berguna jika Anda juga perlu melakukan beberapa operasi lain pada setiap elemen sebelum penghapusan.
var index = array.count-1 while index >= 0 { let element = array[index] //any operations on element array.remove(at: index) index -= 1 }
sumber
Saya merekomendasikan untuk mengatur elemen menjadi nol selama pencacahan, dan setelah menyelesaikan hapus semua elemen kosong menggunakan metode array filter ().
sumber
filter
metode ini tidak menghapus, ini menghasilkan array baru.Sebagai tambahan, jika Anda memiliki banyak array dan setiap elemen dalam indeks N dari array A terkait dengan indeks N dari array B, maka Anda masih dapat menggunakan metode untuk membalikkan array yang disebutkan (seperti jawaban sebelumnya). Tapi ingat bahwa saat mengakses dan menghapus elemen dari array lain, tidak perlu membalikkannya.
Like so, (one can copy and paste this on Playground) var a = ["a", "b", "c", "d"] var b = [1, 2, 3, 4] var c = ["!", "@", "#", "$"] // remove c, 3, # for (index, ch) in a.enumerated().reversed() { print("CH: \(ch). INDEX: \(index) | b: \(b[index]) | c: \(c[index])") if ch == "c" { a.remove(at: index) b.remove(at: index) c.remove(at: index) } } print("-----") print(a) // ["a", "b", "d"] print(b) // [1, 2, 4] print(c) // ["!", "@", "$"]
sumber