extension Array {
func removeObject<T where T : Equatable>(object: T) {
var index = find(self, object)
self.removeAtIndex(index)
}
}
Namun, saya mendapatkan kesalahan var index = find(self, object)
'T' tidak dapat dikonversi menjadi 'T'
Saya juga mencoba dengan metode tanda tangan ini:, func removeObject(object: AnyObject)
namun, saya mendapatkan kesalahan yang sama:
'AnyObject' tidak dapat dikonversi menjadi 'T'
Apa cara yang tepat untuk melakukan ini?
T where
dari deklarasi metode Anda. Jadi adil sajafunc removeObject<T: Equatable>
. Pertanyaan ini terkait: stackoverflow.com/questions/24091046/…Jawaban:
Pada Swift 2 , ini dapat dicapai dengan metode ekstensi protokol .
removeObject()
didefinisikan sebagai metode pada semua jenis yang sesuai denganRangeReplaceableCollectionType
(khususnya padaArray
) jika elemen koleksi adalahEquatable
:Contoh:
Pembaruan untuk Swift 2 / Xcode 7 beta 2: Seperti yang diperlihatkan oleh Airspeed Velocity dalam komentar, sekarang mungkin untuk menulis metode pada tipe generik yang lebih ketat pada templat, sehingga metode tersebut sekarang dapat didefinisikan sebagai ekstensi dari
Array
:Ekstensi protokol masih memiliki keuntungan untuk diterapkan pada serangkaian tipe yang lebih besar.
Pembaruan untuk Swift 3:
sumber
remove(object: Element)
untuk memenuhi pedoman desain API Swift dan menghindari verbositas. Saya telah mengirimkan hasil edit yang mencerminkan hal ini.Anda tidak dapat menulis metode pada tipe generik yang lebih membatasi pada templat.
CATATAN : pada Swift 2.0, kini Anda dapat menulis metode yang berada lebih ketat pada template. Jika Anda telah memutakhirkan kode Anda ke 2.0, lihat jawaban lain lebih jauh ke bawah untuk opsi baru untuk mengimplementasikan ekstensi ini menggunakan.
Alasan Anda mendapatkan kesalahan
'T' is not convertible to 'T'
adalah bahwa Anda sebenarnya mendefinisikan yang baru T dalam metode Anda yang sama sekali tidak terkait dengan T. asli. Jika Anda ingin menggunakan T dalam metode Anda, Anda dapat melakukannya tanpa menentukannya pada metode Anda.Alasan Anda mendapatkan kesalahan kedua
'AnyObject' is not convertible to 'T'
adalah bahwa semua nilai yang mungkin untuk T tidak semua kelas. Untuk instance yang akan dikonversi ke AnyObject, itu harus kelas (itu tidak bisa menjadi struct, enum, dll.).Taruhan terbaik Anda adalah menjadikannya fungsi yang menerima array sebagai argumen:
Atau alih-alih memodifikasi array asli, Anda dapat membuat metode Anda lebih aman dan dapat digunakan kembali dengan mengembalikan salinan:
Sebagai alternatif yang saya tidak rekomendasikan, Anda dapat gagal metode Anda secara diam-diam jika tipe yang disimpan dalam array tidak dapat dikonversi ke templat metode (yang setara). (Untuk kejelasan, saya menggunakan U alih-alih T untuk templat metode ini):
Sunting Untuk mengatasi kegagalan diam, Anda dapat mengembalikan kesuksesan sebagai bool:
sumber
find
metode ini?Equatable
protokol. UIView melakukannya ya itu akan bekerja dengan UIViewsenumerate(self)
harus memperbaiki keself.enumerate()
secara singkat dan singkat:
sumber
inout
juga. Bahkan denganinout
utuh, orang bisa menggunakanarray = array.filter() { $0 != object }
,, saya pikir.Setelah membaca semua hal di atas, menurut saya jawaban terbaik adalah:
Sampel:
Ekstensi array Swift 2 (xcode 7b4):
Sampel:
Pembaruan Swift 3.1
Kembali ke ini sekarang karena Swift 3.1 sedang tidak aktif. Di bawah ini adalah ekstensi yang menyediakan varian lengkap, cepat, bermutasi dan membuat.
Sampel:
sumber
filter
fungsi sudah menangani fungsi itu untuk Anda. Ini tampaknya menduplikasi fungsi. Namun jawaban yang bagus:]Dengan ekstensi protokol Anda dapat melakukan ini,
Fungsionalitas yang sama untuk kelas,
Cepat 2
Cepat 3
Tetapi jika kelas mengimplementasikan Equatable itu menjadi ambigu dan kompiler memberikan kesalahan melempar.
sumber
Binary operator '===' cannot be applied to two elements of type '_' and 'Element'
Dengan menggunakan ekstensi protokol di swift 2.0
sumber
bagaimana dengan menggunakan pemfilteran? berikut ini bekerja dengan cukup baik bahkan dengan [AnyObject].
sumber
Ada kemungkinan lain untuk menghapus item dari array tanpa memiliki kemungkinan penggunaan yang tidak aman, karena tipe generik objek yang akan dihapus tidak boleh sama dengan jenis array. Menggunakan opsional juga bukan cara sempurna untuk digunakan karena sangat lambat. Karena itu Anda bisa menggunakan penutupan seperti itu sudah digunakan saat mengurutkan array misalnya.
Ketika Anda memperluas
Array
kelas dengan fungsi ini, Anda dapat menghapus elemen dengan melakukan hal berikut:Namun Anda bahkan dapat menghapus elemen hanya jika memiliki alamat memori yang sama (tentu saja untuk kelas yang sesuai dengan
AnyObject
protokol):Hal yang baik adalah, Anda dapat menentukan parameter untuk dibandingkan. Misalnya ketika Anda memiliki array array, Anda dapat menentukan penutupan kesetaraan sebagai
{ $0.count == $1.count }
dan array pertama memiliki ukuran yang sama dengan yang akan dihapus dihapus dari array.Anda bahkan dapat mempersingkat pemanggilan fungsi dengan memiliki fungsi sebagai
mutating func removeFirst(equality: (Element) -> Bool) -> Bool
, lalu mengganti if-evaluation denganequality(item)
dan memanggil fungsi denganarray.removeFirst({ $0 == "Banana" })
misalnya.sumber
==
merupakan fungsi, Anda juga dapat menyebutnya seperti ini untuk semua jenis yang mengimplementasikan==
(seperti String, Int, dll.):array.removeFirst("Banana", equality:==)
Tidak perlu diperpanjang:
sumber
Menggunakan
indexOf
bukannya afor
atauenumerate
:sumber
Mungkin saya tidak mengerti pertanyaannya.
Mengapa ini tidak berhasil?
sumber
Saya akhirnya berakhir dengan kode berikut.
sumber
Saya berhasil menghapus
[String:AnyObject]
dari array[[String:AnyObject]]
dengan menerapkan hitungan di luar loop untuk mewakili indeks sejak.find
dan.filter
tidak kompatibel dengan[String:AnyObject]
.sumber
Implementasi dalam Swift 2:
sumber
Saya bisa membuatnya bekerja dengan:
sumber
if(index)
tidak valid