Swift 3'te diziden nesneyi çıkarma


93

Uygulamamda hücreyi seçerken diziye bir nesne ekledim ve hücreyi yeniden seçerken nesnenin seçimini kaldırıp kaldırdım. Bu kodu kullandım ama bana hata ver.

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])
    }
}

Bana böyle 2 hata veriyor:

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

Set<Contact>Dizi yerine a kullanabilirsiniz . İletişim nesneniz hakkında daha fazla bilgi verebilir misiniz? Kendiniz yaptıysanız, ona uymak Hashableve Equatablebir sete koymak için ihtiyacınız olacak
Paulw11

Yanıtlar:


167

Swift eşdeğer NSMutableArrayVar removeObjectolan:

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

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

nesneler benzersizse . Cast etmeye NSArrayve kullanmaya hiç gerek yokindexOfObject:

API index(of:de çalışır ancak bu NSArray,.

Aynı nesnenin birden fazla oluşumu varsa kullanın filter. Ancak, bir dizinin belirli bir nesneyle ilişkilendirildiği veri kaynağı dizileri gibi durumlarda firstIndex(of, daha hızlı olduğu için tercih edilir filter.

Güncelleme:

Swift in 4.2+ birini veya birden fazla kopyasını kaldırabilirsiniz betaile removeAll(where:):

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

34
Bu en iyi cevaptır, ancak bir kaldırmaya sahip olmamak aptallığın da ötesindedir (nesne: "beta").
zeeple

5
Bence .index(of: yalnızca koleksiyon Equatabletürleri içeriyorsa kullanılabilir.
Adam Waite

@AdamWaite Evet, ancak bu Foundation türleri için de geçerlidir.
vadian

Bu doğru değil, ya birden fazla "beta" varsa? Bu yalnızca dizi birden fazla oluşum içermediğinde çalışır. Doğru cevap, bir filtre kullanmak veya bu cevabı bir süre sonra çalıştırmaktırwhile let index = array.index(of: "beta") { array.remove(at: index) }
juancazalla

@juancazalla Haklısınız, ancak dizi birden fazla oluşum içeriyorsa filterçözümü kullanın . Ancak nesneler benzersiz kullanımsa, her zaman index(ofolduğundan çok daha performanslı olduğu içinfilter
vadian

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

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

7
Bu, dilin sunduğu söz dizimi güzelliklerini kullanan doğru Swift çözümüdür.
Michael

1
Ya öğe bir nesneyse?
TomSawyer

@TomSawyer, bir nesneyi filtrelemek için 0 $ kullanın! ==
Mike Taverne

25

Swift 3 için, indeksi (burada :) kullanabilir ve dizideki bir nesnenin ($ 0) aradığınız şeyle karşılaştırmasını yapan bir kapanış ekleyebilirsiniz.

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

Birden çok nesneyi kaldırmak istersem bu işe yarar mı? gibi (burada: {$ 0 == "beta" || $ 0 == "gamma"})
Irshad Mohamed

16

Bir başka güzel ve kullanışlı çözüm de bu tür bir uzantı oluşturmaktır:

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
    }

}

Bu şekilde, dizinize özel nesneler sahipseniz:

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
Bu yalnızca dizi birden fazla oluşum içermediğinde çalışır. Doğru cevap, bir filtre kullanmak veya bu cevabı bir süre sonra çalıştırmaktır. Bu uzantının bir kullanıcısı olarak, yalnızca birini değil, tüm oluşumlarını kaldırmasını bekliyorum
juancazalla

Güzel, ancak remove(element: Element)Array'de Int, Double gibi türleri de depolayabileceğiniz için olması gerekir - bunlar nesne değildir.
Radek Wilczak

8

In Swift 5 , bunu kullanın Extension:

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

misal:

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

In Swift 3 , bunu kullanın Extension:

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

misal:

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

6
  1. for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) C-stilinde döngü içindir ve kaldırılmıştır

  2. Döngüye sahipse tüm benzer nesneleri kaldırmak için kodunuzu buna benzer bir şeye değiştirin:

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

numaralandırılmış -> filtre -> eşleme ve kaldırma (at) akıllı bir çözümdür. Bunu tavsiye et
Ryan X

4

Swift 4

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

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

3

Swift 3'te bu nesnelerin bir dizisinden ("dizi" olarak adlandırılan) benzersiz bir nesneyi ("objectToRemove" adlı) silmek için doğru ve çalışan tek satırlık çözüm şudur:

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

1

Bunu Swift 3'te deneyin

array.remove(at: Index)

Onun yerine

array.removeAtIndex(index)

Güncelleme

"Declaration is only valid at file scope".

Nesnenin kapsam içinde olduğundan emin olun. Varsayılan olan "dahili" kapsamı verebilirsiniz.

index(of:<Object>) çalışmak, sınıf uymak zorundadır Equatable


1

Gelen Swift 3 ve 4'e

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

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

Gönderen Swift 4.2 Daha gelişmiş bir yaklaşım (daha hızlı ve hafızayı verimli) kullanabilir

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

onun yerine

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

Daha fazlasını buradan okuyun


1

Dizinin kolayca yapması ve Swift 4.2 ve üzeri için zincirlemeye izin veren uzantı:

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
    }
}

Bağımsız değişken etiketleri '(burada :)' mevcut aşırı
yüklerle eşleşmiyor

1
@ jeet.chanchawat iyi muhtemelen farklı hızlı sürüm o zaman ... Bu soru 3 için miydi? Sanırım yazarken 4.2 vardı ama şimdi hatırlamıyorum, daha sonra kontrol edeceğim, kesinlikle benim için çalıştı
Renetik


0

Kullandığım şey bu (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)

Sonuçlar:

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

Önemli: Öğeleri çıkardığınız dizi, Eşleştirilebilir öğeler (nesneler, dizeler, sayı vb.) İçermelidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.