Cara memeriksa apakah suatu elemen ada dalam array

475

Di Swift, bagaimana saya bisa memeriksa apakah ada elemen dalam array? Xcode tidak memiliki saran untuk contain, include, atau has, dan pencarian cepat melalui buku muncul apa-apa. Adakah yang tahu cara memeriksa ini? Saya tahu bahwa ada metode findyang mengembalikan nomor indeks, tetapi apakah ada metode yang mengembalikan boolean seperti ruby #include??

Contoh yang saya butuhkan:

var elements = [1,2,3,4,5]
if elements.contains(5) {
  //do something
}
jaredsmith
sumber
11
if find(elements, 5) != nil { }tidak cukup baik
Martin R
1
Saya berharap untuk sesuatu yang lebih bersih, tetapi tidak terlihat bagus. Saya belum menemukan apa pun di dokumentasi atau buku.
jaredsmith

Jawaban:

860

Swift 2, 3, 4, 5:

let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
    print("yes")
}

contains()adalah metode ekstensi protokol dari SequenceType(untuk urutan Equatableelemen) dan bukan metode global dalam rilis sebelumnya.

Catatan:

Versi cepat Swift:

let elements = [1,2,3,4,5]
if contains(elements, 5) {
    println("yes")
}
Martin R
sumber
4
Adakah dokumentasi tentang fungsi global semacam ini?
Rivera
3
Apakah ini seharusnya berfungsi jika setiap item di dalam array (dan item yang kita cari) bertipe Kamus <String, AnyObject>? Mencoba untuk mencapai itu tetapi saya mendapatkan kesalahan waktu kompilasi.
ppalancica
7
@ ppalancica: Ini mensyaratkan bahwa elemen array sesuai dengan Equatableprotokol (yang Dictionary<String, AnyObject>tidak). Ada varian kedua contains()yang mengambil predikat (bandingkan stackoverflow.com/questions/29679486/... ) mungkin Anda dapat menggunakannya, misalnyaif contains(array, { $0 == dict } ) ...
Martin R
Bagaimana cara mencari elemen spesifik dari array generik? katakan [AnyObject]?
Dhaval H. Nena
127

Bagi mereka yang datang ke sini mencari menemukan dan menghapus objek dari array:

Cepat 1

if let index = find(itemList, item) {
    itemList.removeAtIndex(index)
}

Cepat 2

if let index = itemList.indexOf(item) {
    itemList.removeAtIndex(index)
}

Cepat 3, 4

if let index = itemList.index(of: item) {
    itemList.remove(at: index)
}

Cepat 5.2

if let index = itemList.firstIndex(of: item) {
    itemList.remove(at: index)
}
DogCoffee
sumber
3
Harap jawab pertanyaan yang relevan. Pertanyaan ini hanya bertanya tentang menemukan elemen dalam array, tidak menghapus atau memperbaruinya. Anda dapat mengajukan pertanyaan terpisah dan menjawabnya sendiri juga.
Tejas
60

Gunakan ekstensi ini:

extension Array {
    func contains<T where T : Equatable>(obj: T) -> Bool {
        return self.filter({$0 as? T == obj}).count > 0
    }
}

Digunakan sebagai:

array.contains(1)

Diperbarui untuk Swift 2/3

Perhatikan bahwa pada Swift 3 (atau bahkan 2), ekstensi tidak lagi diperlukan karena containsfungsi global telah dibuat menjadi sepasang metode ekstensi aktif Array, yang memungkinkan Anda melakukan salah satu dari:

let a = [ 1, 2, 3, 4 ]

a.contains(2)           // => true, only usable if Element : Equatable

a.contains { $0 < 1 }   // => false
David Berry
sumber
10
temukan lebih cepat.
Jim Balter
1
tergantung pada apa yang Anda terbiasa, .cains mungkin merasa lebih intuitif dan mudah diingat
Pirijan
4
Bisakah Anda menjelaskan sintaks Anda dengan memecahnya? Saya belum pernah melihat pemformatan ini sebelumnya dan Anda memiliki banyak hal canggih yang terjadi sekaligus!
Aggressor
40

Jika Anda memeriksa apakah instance kelas kustom atau struct terkandung dalam array, Anda harus mengimplementasikan protokol Equatable sebelum Anda dapat menggunakan .contains (myObject).

Sebagai contoh:

struct Cup: Equatable {
    let filled:Bool
}

static func ==(lhs:Cup, rhs:Cup) -> Bool { // Implement Equatable
    return lhs.filled == rhs.filled
}

maka kamu bisa melakukan:

cupArray.contains(myCup)

Tip : Override == harus di tingkat global, bukan di dalam kelas / struct Anda

Andrew Schreiber
sumber
32

Saya menggunakan filter.

let results = elements.filter { el in el == 5 }
if results.count > 0 {
    // any matching items are in results
} else {
    // not found
}

Jika mau, Anda bisa mengompresnya ke

if elements.filter({ el in el == 5 }).count > 0 {
}

Semoga itu bisa membantu.


Pembaruan untuk Swift 2

Hore untuk implementasi standar!

if elements.contains(5) {
    // any matching items are in results
} else {
    // not found
}
Jeffery Thomas
sumber
Saya suka solusi filter karena Anda dapat menggunakannya untuk semua hal. Sebagai contoh, saya porting beberapa kode yang berulang dan berulang mencoba untuk melihat apakah daftar sudah memiliki item dengan salah satu bidang yang berisi nilai string. Ini satu baris di Swift, menggunakan filter pada bidang itu.
Maury Markowitz
filter tidak efisien karena selalu mengulang semua elemen alih-alih kembali segera ketika elemen ditemukan. Sebaiknya gunakan find ().
Thorsten
19

(Swift 3)

Periksa apakah ada elemen dalam array (memenuhi beberapa kriteria), dan jika demikian, lanjutkan bekerja dengan elemen tersebut pertama

Jika tujuannya adalah:

  1. Untuk memeriksa apakah suatu elemen ada dalam array (/ memenuhi beberapa kriteria boolean, belum tentu pengujian kesetaraan),
  2. Dan jika demikian, lanjutkan dan bekerja dengan elemen seperti pertama,

Maka alternatif untuk contains(_:)sebagai cetak biru Sequenceadalah first(where:)dari Sequence:

let elements = [1, 2, 3, 4, 5]

if let firstSuchElement = elements.first(where: { $0 == 4 }) {
    print(firstSuchElement) // 4
    // ...
}

Dalam contoh yang dibuat-buat ini, penggunaannya mungkin tampak konyol, tetapi sangat berguna jika permintaan array tipe elemen non-fundamental untuk keberadaan elemen yang memenuhi beberapa persyaratan. Misalnya

struct Person {
    let age: Int
    let name: String
    init(_ age: Int, _ name: String) {
        self.age = age
        self.name = name
    }
}

let persons = [Person(17, "Fred"),   Person(16, "Susan"),
               Person(19, "Hannah"), Person(18, "Sarah"),
               Person(23, "Sam"),    Person(18, "Jane")]

if let eligableDriver = persons.first(where: { $0.age >= 18 }) {
    print("\(eligableDriver.name) can possibly drive the rental car in Sweden.")
    // ...
} // Hannah can possibly drive the rental car in Sweden.

let daniel = Person(18, "Daniel")
if let sameAgeAsDaniel = persons.first(where: { $0.age == daniel.age }) {
    print("\(sameAgeAsDaniel.name) is the same age as \(daniel.name).")
    // ...
} // Sarah is the same age as Daniel.

Setiap operasi berantai menggunakan .filter { ... some condition }.firstdapat diganti dengan baik first(where:). Yang terakhir menunjukkan niat yang lebih baik, dan memiliki keunggulan kinerja lebih dari peralatan yang tidak malas .filter, karena ini akan melewati array penuh sebelum mengekstraksi elemen (mungkin) pertama yang melewati filter.


Periksa apakah ada elemen dalam array (memenuhi beberapa kriteria), dan jika demikian, hapus elemen pertama

Komentar di bawah pertanyaan:

Bagaimana saya bisa menghapus firstSuchElementdari array?

Kasus penggunaan yang mirip dengan yang di atas adalah untuk menghapus elemen pertama yang memenuhi predikat yang diberikan. Untuk melakukannya, index(where:)metode Collection(yang sudah tersedia untuk koleksi array) dapat digunakan untuk menemukan indeks elemen pertama yang memenuhi predikat, kemudian indeks dapat digunakan dengan remove(at:)metode Arrayto (mungkin; mengingat bahwa itu ada) hapus elemen itu.

var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]

if let indexOfFirstSuchElement = elements.index(where: { $0 == "c" }) {
    elements.remove(at: indexOfFirstSuchElement)
    print(elements) // ["a", "b", "d", "e", "a", "b", "c"]
}

Atau, jika Anda ingin menghapus elemen dari array dan bekerja dengannya , terapkan metode Optional: s map(_:)untuk bersyarat (untuk .some(...)kembali dari index(where:)) gunakan hasil dari index(where:)untuk menghapus dan menangkap elemen yang dihapus dari array (dalam klausa penjilidan opsional) .

var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]

if let firstSuchElement = elements.index(where: { $0 == "c" })
    .map({ elements.remove(at: $0) }) {

    // if we enter here, the first such element have now been
    // remove from the array
    print(elements) // ["a", "b", "d", "e", "a", "b", "c"]

    // and we may work with it
    print(firstSuchElement) // c
}

Perhatikan bahwa dalam contoh yang dibuat di atas anggota array adalah tipe nilai sederhana ( Stringinstance), jadi menggunakan predikat untuk menemukan anggota tertentu agak terlalu mematikan, karena kami mungkin hanya menguji kesetaraan menggunakan index(of:)metode yang lebih sederhana seperti yang ditunjukkan pada jawaban @ DogCoffee . Jika menerapkan pendekatan temukan-dan-hilangkan di atas untuk Personcontoh, bagaimanapun, menggunakan index(where:)dengan predikat adalah tepat (karena kami tidak lagi menguji kesetaraan tetapi untuk memenuhi predikat yang disediakan).

dfri
sumber
Bagaimana saya bisa menghapus firstSuchElement dari array?
i6x86
@ i6x86 terima kasih atas pertanyaannya. Saya memperbarui jawaban saya dengan contoh cara menghapus elemen (dan juga cara menghapus dan menangkap elemen yang dihapus).
dfri
14

Cara termudah untuk mencapai ini adalah dengan menggunakan filter pada array.

let result = elements.filter { $0==5 }

resultakan memiliki elemen yang ditemukan jika ada dan akan kosong jika elemen tidak ada. Jadi cukup memeriksa jika resultkosong akan memberi tahu Anda apakah ada elemen dalam array. Saya akan menggunakan yang berikut ini:

if result.isEmpty {
    // element does not exist in array
} else {
    // element exists
}
davetw12
sumber
solusi hebat jadi metode ini mengembalikan array. Namun, saya menggunakan ini untuk mencari "id". Dalam aplikasi saya unik, jadi hanya ada satu hasil. Apakah ada cara untuk mengembalikan hanya 1 hasil? Saya menggunakan hasil [0] untuk saat ini
Dan Beaulieu
3
@DanBeaulieu Melakukan sesuatu seperti let result = elements.filter { $0==5 }.firstharus memenuhi apa yang Anda cari.
davetw12
7

Swift 4/5

Cara lain untuk mencapai ini adalah dengan fungsi filter

var elements = [1,2,3,4,5]
if let object = elements.filter({ $0 == 5 }).first {
    print("found")
} else {
    print("not found")
}
Pramod More
sumber
6

Pada Swift 2.1 NSArrays memiliki containsObjectyang dapat digunakan seperti:

if myArray.containsObject(objectImCheckingFor){
    //myArray has the objectImCheckingFor
}
ColossalChris
sumber
4
Sebenarnya itu untuk NSArray. Bukan deretan cepat
Tycho Pandelaar
Ya, tetapi Anda dapat mengonversi sementara array cepat Anda ke NSArray: jika biarkan tempNSArrayForChecking = mySwiftArray sebagai NSArray? di mana tempNSArrayForChecking.containsObject (objectImCheckingFor) {// myArray memiliki objek}
Vitalii
4

Untuk berjaga-jaga kalau-kalau ada yang mencoba mencari apakah indexPathada di antara yang terpilih (seperti dalam UICollectionViewatau UITableView cellForItemAtIndexPathfungsi):

    var isSelectedItem = false
    if let selectedIndexPaths = collectionView.indexPathsForSelectedItems() as? [NSIndexPath]{
        if contains(selectedIndexPaths, indexPath) {
            isSelectedItem = true
        }
    }
Ali
sumber
4

Himpunan

let elements = [1, 2, 3, 4, 5, 5]

Periksa keberadaan elemen

elements.contains(5) // true

Dapatkan indeks elemen

elements.firstIndex(of: 5) // 4
elements.firstIndex(of: 10) // nil

Dapatkan jumlah elemen

let results = elements.filter { element in element == 5 }
results.count // 2
Sazzad Hissain Khan
sumber
3

Ini adalah ekstensi kecil saya, saya baru saja menulis untuk memeriksa apakah array delegasi saya berisi objek delegasi atau tidak ( Swift 2 ). :) Ini juga berfungsi dengan tipe nilai seperti pesona.

extension Array
{
    func containsObject(object: Any) -> Bool
    {
        if let anObject: AnyObject = object as? AnyObject
        {
            for obj in self
            {
                if let anObj: AnyObject = obj as? AnyObject
                {
                    if anObj === anObject { return true }
                }
            }
        }
        return false
    }
}

Jika Anda memiliki ide bagaimana mengoptimalkan kode ini, daripada hanya beri tahu saya.

DevAndArtist
sumber
2

jika pengguna menemukan elemen array tertentu maka gunakan kode di bawah ini sama dengan nilai integer.

var arrelemnts = ["sachin", "test", "test1", "test3"]

 if arrelemnts.contains("test"){
    print("found")   }else{
    print("not found")   }
Yogesh Shelke
sumber
2

Cepat

Jika Anda tidak menggunakan objek maka Anda dapat menggunakan kode ini untuk memuat.

let elements = [ 10, 20, 30, 40, 50]

if elements.contains(50) {

   print("true")

}

Jika Anda menggunakan NSObject Class dengan cepat. Variabel ini sesuai dengan kebutuhan saya. Anda dapat memodifikasi untuk kebutuhan Anda.

var cliectScreenList = [ATModelLeadInfo]()
var cliectScreenSelectedObject: ATModelLeadInfo!

Ini untuk tipe data yang sama.

{ $0.user_id == cliectScreenSelectedObject.user_id }

Jika Anda ingin jenis AnyObject.

{ "\($0.user_id)" == "\(cliectScreenSelectedObject.user_id)" }

Kondisi penuh

if cliectScreenSelected.contains( { $0.user_id == cliectScreenSelectedObject.user_id } ) == false {

    cliectScreenSelected.append(cliectScreenSelectedObject)

    print("Object Added")

} else {

    print("Object already exists")

 }
Anit Kumar
sumber
1

bagaimana dengan menggunakan tabel hash untuk pekerjaan itu, seperti ini?

pertama, membuat fungsi generik "peta hash", memperluas protokol Sequence.

extension Sequence where Element: Hashable {

    func hashMap() -> [Element: Int] {
        var dict: [Element: Int] = [:]
        for (i, value) in self.enumerated() {
            dict[value] = i
        }
        return dict
    }
}

Ekstensi ini akan berfungsi selama item dalam array sesuai dengan Hashable, seperti bilangan bulat atau string, berikut adalah penggunaannya ...

let numbers = Array(0...50) 
let hashMappedNumbers = numbers.hashMap()

let numToDetect = 35

let indexOfnumToDetect = hashMappedNumbers[numToDetect] // returns the index of the item and if all the elements in the array are different, it will work to get the index of the object!

print(indexOfnumToDetect) // prints 35

Tapi untuk sekarang, mari kita fokus memeriksa apakah elemennya ada di dalam array.

let numExists = indexOfnumToDetect != nil // if the key does not exist 
means the number is not contained in the collection.

print(numExists) // prints true
James Rochabrun
sumber
0

Swift 4.2 +
Anda dapat dengan mudah memverifikasi instance Anda berupa array atau tidak dengan fungsi berikut.

func verifyIsObjectOfAnArray<T>(_ object: T) -> Bool {
   if let _ = object as? [T] {
      return true
   }

   return false
}

Bahkan Anda dapat mengaksesnya sebagai berikut. Anda akan menerima niljika objek tidak berupa array.

func verifyIsObjectOfAnArray<T>(_ object: T) -> [T]? {
   if let array = object as? [T] {
      return array
   }

   return nil
}
Kiran Jasvanee
sumber