Menghapus objek dari array di Swift 3


93

Dalam aplikasi saya, saya menambahkan satu objek dalam array ketika memilih sel dan membatalkan pilihan dan menghapus objek saat memilih ulang sel. Saya menggunakan kode itu tetapi memberi saya kesalahan.

extension Array {
    func indexOfObject(object : AnyObject) -> NSInteger {
        return (self as NSArray).indexOfObject(object)
    }

    mutating func removeObject(object : AnyObject) {
        for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) {
            self.removeAtIndex(index)
        }
    }
}

class MyViewController: UITableViewController {
    var arrContacts: [Any] = []
    var contacts: [Any] = []

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        arrContacts.removeObject(contacts[indexPath.row])
    }
}

Ini memberi saya 2 kesalahan seperti itu:

C-style for statement has been removed in Swift 3
Value of type '[Any]' has no member 'removeObject'

Anda dapat menggunakan Set<Contact>daripada Array. Dapatkah Anda memberikan lebih banyak informasi tentang objek kontak Anda? Jika Anda membuatnya sendiri, Anda akan membutuhkannya untuk menyesuaikan Hashabledan Equatableuntuk meletakkannya dalam satu set
Paulw11

Jawaban:


167

Persamaan Swift dengan NSMutableArray's removeObjectadalah:

var array = ["alpha", "beta", "gamma"]

if let index = array.firstIndex(of: "beta") {
    array.remove(at: index)
}

jika objeknya unik . Tidak perlu sama sekali untuk mentransmisikan NSArraydan menggunakanindexOfObject:

API index(of:juga berfungsi tetapi hal ini menyebabkan transmisi implisit yang tidak perlu dilakukan NSArray.

Jika ada beberapa kejadian penggunaan objek yang sama filter. Namun dalam kasus seperti larik sumber data di mana indeks dikaitkan dengan objek tertentu firstIndex(oflebih disukai karena lebih cepat daripada filter.

Memperbarui:

Di Swift 4.2+ Anda dapat menghapus satu atau beberapa kejadian betadengan removeAll(where:):

array.removeAll{$0 == "beta"}

34
Ini adalah jawaban terbaik, tetapi sangat bodoh untuk tidak menghapusnya (object: "beta").
zeeple

5
Menurut saya .index(of: hanya tersedia jika koleksi berisi Equatablejenis.
Adam Waite

@AdamWaite Ya, tetapi ini juga berlaku untuk jenis Foundation.
vadian

Ini tidak benar, bagaimana jika Anda memiliki lebih dari satu "beta"? Ini hanya berfungsi jika array tidak berisi lebih dari satu kejadian. Jawaban yang benar adalah menggunakan filter atau menjalankan jawaban ini sebentar lagi,while let index = array.index(of: "beta") { array.remove(at: index) }
juancazalla

@juancazalla Anda benar, tetapi dalam kasus jika array dapat berisi lebih dari satu kejadian, gunakan filtersolusi. Tetapi jika objeknya unik, gunakan selalu index(ofkarena performanya jauh lebih baik daripadafilter
vadian

72
var a = ["one", "two", "three", "four", "five"]

// Remove/filter item with value 'three'
a = a.filter { $0 != "three" }

7
Itu adalah solusi Swift yang tepat, yang memanfaatkan barang sintaksis yang ditawarkan oleh bahasa tersebut.
Michael

1
Bagaimana jika barang adalah benda?
TomSawyer

@TomSawyer untuk menyaring objek, gunakan $ 0! ==
Mike Taverne

25

Untuk Swift 3, Anda dapat menggunakan index (di mana :) dan menyertakan closure yang melakukan perbandingan objek dalam array ($ 0) dengan apa pun yang Anda cari.

var array = ["alpha", "beta", "gamma"]
if let index = array.index(where: {$0 == "beta"}) {
  array.remove(at: index)
}

apakah ini akan berfungsi jika saya ingin menghapus beberapa objek? suka (di mana: {$ 0 == "beta" || $ 0 == "gamma"})
Irshad Mohamed

16

Solusi bagus dan berguna lainnya adalah dengan membuat ekstensi semacam ini:

extension Array where Element: Equatable {

    @discardableResult mutating func remove(object: Element) -> Bool {
        if let index = index(of: object) {
            self.remove(at: index)
            return true
        }
        return false
    }

    @discardableResult mutating func remove(where predicate: (Array.Iterator.Element) -> Bool) -> Bool {
        if let index = self.index(where: { (element) -> Bool in
            return predicate(element)
        }) {
            self.remove(at: index)
            return true
        }
        return false
    }

}

Dengan cara ini, jika Anda memiliki array Anda dengan objek kustom:

let obj1 = MyObject(id: 1)
let obj2 = MyObject(id: 2)
var array: [MyObject] = [obj1, obj2]

array.remove(where: { (obj) -> Bool in
    return obj.id == 1
})
// OR
array.remove(object: obj2) 

1
Ini hanya berfungsi jika array tidak berisi lebih dari satu kejadian. Jawaban yang benar adalah menggunakan filter atau menjalankan jawaban ini sebentar. Sebagai pengguna ekstensi ini, saya mengharapkannya untuk menghapus semua kejadian dan tidak hanya satu
juancazalla

Itu bagus, tetapi seharusnya remove(element: Element)karena dalam Array Anda juga dapat menyimpan tipe seperti Int, Double - mereka bukan objek.
Radek Wilczak

8

Di Swift 5 , Gunakan ini Extension:

extension Array where Element: Equatable{
    mutating func remove (element: Element) {
        if let i = self.firstIndex(of: element) {
            self.remove(at: i)
        }
    }
}

contoh:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

Di Swift 3 , Gunakan ini Extension:

extension Array where Element: Equatable{
    mutating func remove (element: Element) {
        if let i = self.index(of: element) {
            self.remove(at: i)
        }
    }
}

contoh:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

6
  1. for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) adalah untuk loop dalam gaya C dan telah dihapus

  2. Ubah kode Anda menjadi sesuatu seperti ini untuk menghapus semua objek serupa jika telah berulang:

    let indexes = arrContacts.enumerated().filter { $0.element == contacts[indexPath.row] }.map{ $0.offset }
    for index in indexes.reversed() {
       arrContacts.remove(at: index)
    }
    

enumerated -> filter -> map and remove (at) adalah solusi cerdas. Rekomendasikan yang ini
Ryan X

4

Cepat 4

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]

if let index = students.firstIndex(where: { $0.hasPrefix("A") }) {
   students.remove(at: index)
}

3

Solusi satu baris yang benar dan berfungsi untuk menghapus objek unik (bernama "objectToRemove") dari array objek ini (bernama "array") di Swift 3 adalah:

if let index = array.enumerated().filter( { $0.element === objectToRemove }).map({ $0.offset }).first {
   array.remove(at: index)
}

1

Coba ini di Swift 3

array.remove(at: Index)

Dari pada

array.removeAtIndex(index)

Memperbarui

"Declaration is only valid at file scope".

Pastikan objek dalam ruang lingkup. Anda dapat memberikan ruang lingkup "internal", yang default.

index(of:<Object>) untuk bekerja, kelas harus sesuai Equatable


1

Di Swift 3 dan 4

var array = ["a", "b", "c", "d", "e", "f"]

for (index, element) in array.enumerated().reversed() {
    array.remove(at: index)
}

Dari Swift 4.2 Anda dapat menggunakan pendekatan yang lebih canggih (lebih cepat dan hemat memori)

array.removeAll(where: { $0 == "c" })

dari pada

array = array.filter { !$0.hasPrefix("c") }

Baca lebih lanjut di sini


1

Ekstensi untuk array untuk melakukannya dengan mudah dan memungkinkan perangkaian untuk Swift 4.2 dan yang lebih baru:

public extension Array where Element: Equatable {
    @discardableResult
    public mutating func remove(_ item: Element) -> Array {
        if let index = firstIndex(where: { item == $0 }) {
            remove(at: index)
        }
        return self
    }

    @discardableResult
    public mutating func removeAll(_ item: Element) -> Array {
        removeAll(where: { item == $0 })
        return self
    }
}

Label argumen '(di mana :)' tidak cocok dengan kelebihan beban yang tersedia
jeet.chanchawat

1
@ jeet.chanchawat yah mungkin versi swiftnya berbeda ... Oh pertanyaan ini untuk 3? Yah saya pikir saya punya 4.2 pada saat menulis tetapi tidak ingat sekarang, akan memeriksanya nanti, itu pasti berhasil untuk saya
Renetik


0

Ini yang saya gunakan (Swift 5) ...

    extension Array where Element:Equatable
    {
        @discardableResult
        mutating func removeFirst(_ item:Any ) -> Any? {
            for index in 0..<self.count {
                if(item as? Element == self[index]) {
                    return self.remove(at: index)
                }
            }
            return nil
        }
        @discardableResult
        mutating func removeLast(_ item:Any ) -> Any? {
            var index = self.count-1
            while index >= 0 {
                if(item as? Element == self[index]) {
                    return self.remove(at: index)
                }
                index -= 1
            }
            return nil
        }
    }

    var arrContacts:[String] = ["A","B","D","C","B","D"]
    var contacts: [Any] = ["B","D"]
    print(arrContacts)
    var index = 1
    arrContacts.removeFirst(contacts[index])
    print(arrContacts)
    index = 0
    arrContacts.removeLast(contacts[index])
    print(arrContacts)

Hasil:

   ["A", "B", "D", "C", "B", "D"]
   ["A", "B", "C", "B", "D"]
   ["A", "B", "C", "D"]

Penting: Larik tempat Anda menghapus item harus berisi elemen yang dapat disamakan (seperti objek, string, angka, dll.)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.