Swift'te liste öğesinin dizinini nasıl bulabilirim?


443

Ben item indexarayarak bir bulmaya çalışıyorum list. Bunu nasıl yapacağını bilen var mı?

Anlıyorum list.StartIndexve list.EndIndexpython gibi bir şey istiyorum list.index("text").

Yanıtlar:


823

Swift bazı açılardan nesne yönelimli olduğundan daha işlevsel olduğundan (ve Diziler nesneler değil yapılardır), isteğe bağlı bir değer döndüren dizide çalışmak için "find" işlevini kullanın, bu nedenle nil değerini işlemeye hazır olun:

let arr:Array = ["a","b","c"]
find(arr, "c")!              // 2
find(arr, "d")               // nil

Swift 2.0 için güncelleme:

Eski findişlev artık Swift 2.0 ile desteklenmiyor!

Swift 2.0 ile, Arraybir uzantısında CollectionType( Arrayuygulayan) tanımlanan bir işlevi kullanarak bir öğenin dizinini bulma yeteneği kazanır :

let arr = ["a","b","c"]

let indexOfA = arr.indexOf("a") // 0
let indexOfB = arr.indexOf("b") // 1
let indexOfD = arr.indexOf("d") // nil

Ayrıca, bir dizideki yüklemi yerine getiren ilk öğeyi bulmak, aşağıdakilerin başka bir uzantısı tarafından desteklenir CollectionType:

let arr2 = [1,2,3,4,5,6,7,8,9,10]
let indexOfFirstGreaterThanFive = arr2.indexOf({$0 > 5}) // 5
let indexOfFirstGreaterThanOneHundred = arr2.indexOf({$0 > 100}) // nil

Bu iki işlevin finddaha önce olduğu gibi isteğe bağlı değerler döndürdüğünü unutmayın .

Swift 3.0 için güncelleme:

İndexOf sözdiziminin değiştiğini unutmayın. Size uygun öğeler için Equatableşunları kullanabilirsiniz:

let indexOfA = arr.index(of: "a")

Yöntemin ayrıntılı bir belgesini https://developer.apple.com/reference/swift/array/1689674-index adresinde bulabilirsiniz.

Uymayan dizi öğeleri için Equatableşunları kullanmanız gerekir index(where:):

let index = cells.index(where: { (item) -> Bool in
  item.foo == 42 // test if this is the item you're looking for
})

Swift 4.2 Güncellemesi:

Swift 4.2 ile indexartık kullanılmamaktadır, ancak daha iyi açıklama için firstIndexve içine ayrılmıştır lastIndex. Dolayısıyla, öğenin ilk veya son dizinini aramanıza bağlı olarak:

let arr = ["a","b","c","a"]

let indexOfA = arr.firstIndex(of: "a") // 0
let indexOfB = arr.lastIndex(of: "a") // 3

22
Bulma işlevi hakkında nereden öğrendin? Ben "Bul" herhangi belgelerine veya başka bir küresel fonksiyonları bulmak gibi olamaz
Johannes

14
OOP dünyasından gelince, bu tür serbest yüzer fonksiyonları nasıl bulabilirim?
Rudolf Adamkovič

4
Büyük ölçüde belgelenmemiş görünüyorlar. Bir liste için practiswift.com/2014/06/14/… 'e bakın (ancak listenin eksiksiz veya güncel olup olmadığını kontrol etmediğimi unutmayın).
Sebastian Schuth

5
Johannes ve @Rudolf - Dash.app kullanın. Belgelere göz atmak için bir OS X uygulaması. Swift için tüm serbest yüzen işlevlerin bir listesini içeren bir dil referansı vardır. Filtrelemek ve aramak kolaydır. Onsuz yaşayamam.
Bjorn

4
Bilginize: indexOfKendi tanımladığınız bir dizi yapıyı kullanıyorsanız , yapınızın Equatableprotokole uyması gerekir .
Matthew Quiros

202

tl; dr:

Sınıflar için şunları bulabilirsiniz:

let index = someArray.firstIndex{$0 === someObject}

Tam cevap:

Referans türleri ( class) ile bir kimlik karşılaştırması yapmak isteyebileceğinizden bahsetmeye değer olduğunu düşünüyorum , bu durumda sadece ===kimlik operatörünü yüklem kapanışında kullanmanız gerekir :


Hızlı 5, hızlı 4.2:

let person1 = Person(name: "John")
let person2 = Person(name: "Sue")
let person3 = Person(name: "Maria")
let person4 = Person(name: "Loner")

let people = [person1, person2, person3]

let indexOfPerson1 = people.firstIndex{$0 === person1} // 0
let indexOfPerson2 = people.firstIndex{$0 === person2} // 1
let indexOfPerson3 = people.firstIndex{$0 === person3} // 2
let indexOfPerson4 = people.firstIndex{$0 === person4} // nil

Yukarıdaki sözdiziminin sondaki kapanış sözdizimini kullandığını ve şunlara eşdeğer olduğunu unutmayın:

let indexOfPerson1 = people.firstIndex(where: {$0 === person1})


Swift 4 / Swift 3 - eskiden çağrılan işlev index

Swift 2 - eskiden çağrılan işlev indexOf

* Alakalı ve yararlı Not yorumunu tarafından paulbailey hakkında classuygulanması türleri Equatablekullandığınız karşılaştırarak gerekip gerekmediğini dikkate almak gerekir, ===( kimlik operatörü) ya da ==( eşitlik operatörü). Kullanarak eşleşmeye karar verirseniz ==, başkaları tarafından önerilen yöntemi ( people.firstIndex(of: person1)) kullanabilirsiniz.


6
Bu, .indexOf (x) 'in neden çalışmadığını merak edenler için yararlı bir gönderi - bu çözüm beklenmedik ancak geçmişe bakıldığında mükemmel bir şekilde açık.
Maury Markowitz

1
Bunun için çok teşekkürler ama benim için hiç belli değil. Belgelere baktım ve gerçekten neden bir başvuru türü indexOf kullanırken bir yüklemesi kapatılması gerekir anlamıyorum? İndexOf'un referans türlerini zaten kendi başlarına halledebilmesi gerekir. Bunun bir değer türü değil, bir referans türü olduğunu bilmelidir.
Chris

7
Eğer Personuygulanan Equatableprotokol, bu ihtiyaç olmaz.
paulbailey

2
i alıyorum: Binary operator '===' cannot be applied to operands of type '_' and 'Post', Postbenim yapı olduğunu ... bir fikrin?
David Seek

@DavidSeek, structs(ve enums) referans türler değil, değer türleridir. Yalnızca referans türlerinde (örn. class) Kimlik karşılaştırma mantığı ( ===) bulunur. Ne yapacağınızla ilgili diğer cevaplara göz atın structs(temel olarak array.index(of: myStruct), ( ) ile myStructuyumlu olduğundan emin olarak kullanın . Equatable==
Nikolay Suvandzhiev

81

filterKapanışı olan bir dizi yapabilirsiniz :

var myList = [1, 2, 3, 4]
var filtered = myList.filter { $0 == 3 }  // <= returns [3]

Ve bir dizi sayabilirsiniz:

filtered.count // <= returns 1

Yani belirleyebilir eğer bir dizi bu birleştirerek elemanı içerir:

myList.filter { $0 == 3 }.count > 0  // <= returns true if the array includes 3

Pozisyonu bulmak istiyorsanız, süslü bir yol görmüyorum, ama kesinlikle böyle yapabilirsiniz:

var found: Int?  // <= will hold the index if it was found, or else will be nil
for i in (0..x.count) {
    if x[i] == 3 {
        found = i
    }
}

DÜZENLE

Biz oradayken, eğlenceli bir egzersiz Arrayiçin bir findyönteme sahip olalım :

extension Array {
    func find(includedElement: T -> Bool) -> Int? {
        for (idx, element) in enumerate(self) {
            if includedElement(element) {
                return idx
            }
        }
        return nil
    }
}

Şimdi bunu yapabiliriz:

myList.find { $0 == 3 }
// returns the index position of 3 or nil if not found

Funsies için ben yerleşik ne istediğiniz Arraybir findyöntem var genişletmek başka bir örnek ekledi . Bunun iyi bir uygulama olup olmadığını henüz bilmiyorum, ama temiz bir deney.
gwcoffey

2
Sadece şunu belirtmek istiyorum, dokümanlar başına ++ idx kullanmalısınız: "i ++ 'ın özel davranışına ihtiyacınız olmadığı sürece, her durumda ++ i ve --i kullanmanız önerilir, çünkü bunlar i'yi değiştirme ve sonucu döndürme davranışı. "
Logan

İyi karar. Bunu gönderirken enumerate, artık geçerli olmayacak şekilde kullanmak için gözden geçiriyordum, ama kesinlikle haklısın.
gwcoffey

Evet, geçerken örneklerden birinde fark ettiğimi hatırladım. Kendimi şimdi alışkanlık haline getirmeye çalışıyor :)
Logan

4
Bunun Swift 2 / XCode 7 altında çalışması için aşağıdaki gibi değiştirmeniz gerekir. Element: T -> Bool) öğesini (includeElement: Element -> Bool) ile değiştirin ve numaralandırmayı (self) self.enumerate olarak değiştirin
Scooter

35

Hızlı 5

func firstIndex(of element: Element) -> Int?

var alphabets = ["A", "B", "E", "D"]

Örnek 1

let index = alphabets.firstIndex(where: {$0 == "A"})

Örnek2

if let i = alphabets.firstIndex(of: "E") {
    alphabets[i] = "C" // i is the index
}
print(alphabets)
// Prints "["A", "B", "C", "D"]"

25

indexOf()Mükemmel çalışırken , yalnızca bir dizin döndürür.

Ben bazı koşulu tatmin elemanları için bir dizi dizin almak için zarif bir yol arıyordu.

İşte nasıl yapılabilir:

Hızlı 3:

let array = ["apple", "dog", "log"]

let indexes = array.enumerated().filter {
    $0.element.contains("og")
    }.map{$0.offset}

print(indexes)

Hızlı 2:

let array = ["apple", "dog", "log"]

let indexes = array.enumerate().filter {
    $0.element.containsString("og")
    }.map{$0.index}

print(indexes)

12

Özel sınıf için Equatable protokolünü uygulamanız gerekir.

import Foundation

func ==(l: MyClass, r: MyClass) -> Bool {
  return l.id == r.id
}

class MyClass: Equtable {
    init(id: String) {
        self.msgID = id
    }

    let msgID: String
}

let item = MyClass(3)
let itemList = [MyClass(1), MyClass(2), item]
let idx = itemList.indexOf(item)

printl(idx)

9

Swift 2 için güncelleme:

array.contains (element) : Belirli bir dizi (dizi gibi) belirtilen öğeyi içeriyorsa true değerini döndürür.

Hızlı 1:

Bir öğenin bir dizinin içinde bulunup bulunmadığını kontrol etmek istiyorsanız, yani, bir boole göstergesi edinin, contains(sequence, element)yerine şunu kullanın find(array, element):

include (dizi, öğe) : Belirli bir dizi (dizi gibi) belirtilen öğeyi içeriyorsa true değerini döndürür.

Aşağıdaki örneğe bakın:

var languages = ["Swift", "Objective-C"]
contains(languages, "Swift") == true
contains(languages, "Java") == false
contains([29, 85, 42, 96, 75], 42) == true
if (contains(languages, "Swift")) {
  // Use contains in these cases, instead of find.   
}

7

içinde Swift 4.2

:) .Index ( değiştirildi .firstIndex (burada :)

array.firstIndex(where: {$0 == "person1"})

6

Swift 4. Diziniz [String: AnyObject] türünde öğeler içeriyorsa. Öğe dizinini bulmak için aşağıdaki kodu kullanın

var array = [[String: AnyObject]]()// Save your data in array
let objectAtZero = array[0] // get first object
let index = (self.array as NSArray).index(of: objectAtZero)

Veya dizini Sözlük'ten anahtar temelinde bulmak istiyorsanız. Burada dizi Model sınıfı Nesneleri içerir ve ben id özelliği eşleştiriyorum.

   let userId = 20
    if let index = array.index(where: { (dict) -> Bool in
           return dict.id == userId // Will found index of matched id
    }) {
    print("Index found")
    }
OR
      let storeId = Int(surveyCurrent.store_id) // Accessing model key value
      indexArrUpTo = self.arrEarnUpTo.index { Int($0.store_id) == storeId }! // Array contains models and finding specific one

4

Hızlı 2.1

var array = ["0","1","2","3"]

if let index = array.indexOf("1") {
   array.removeAtIndex(index)
}

print(array) // ["0","2","3"]

Hızlı 3

var array = ["0","1","2","3"]

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

3
mutasyon let arraymu yapıyorsun ? Kullanımı selfda şüphelidir.
Chéyo

4

In Swift 4 Eğer DataModel dizisi yoluyla döndürmeyi yerse, yöntem RHS = lhs uygulamak, Equatable Protokolüne emin veri modeli uyan, yapmak ve sadece o zaman "nin (.Index" kullanabilirsiniz. Örneğin

class Photo : Equatable{
    var imageURL: URL?
    init(imageURL: URL){
        self.imageURL = imageURL
    }

    static func == (lhs: Photo, rhs: Photo) -> Bool{
        return lhs.imageURL == rhs.imageURL
    }
}

Ve sonra,

let index = self.photos.index(of: aPhoto)

4

Swift 2'de (Xcode 7 ile), protokol tarafından sağlanan Arraybir indexOfyöntem içerir CollectionType. (Aslında iki indexOfyöntem — biri argümanı eşleştirmek için eşitlik kullanan, diğeri de kapanış kullanan başka bir yöntem.)

Swift 2'den önce, koleksiyonlar gibi jenerik tiplerin onlardan türetilen beton tiplerine (diziler gibi) yöntemler sunmasının bir yolu yoktu. Yani, Swift 1.x, "dizini" küresel bir işlevdir ... Ve aynı zamanda yeniden adlandırıldı, yani Swift 1.x, bu küresel işlev olarak adlandırılır find.

Ayrıca , Swift'in standart kütüphanesinde eşdeğerleri olmayan ... ya da Foundation'ın diğer daha karmaşık arama indexOfObjectyöntemlerinden NSArrayherhangi birini kullanmak da mümkündür (ancak gerekli değildir) . Sadece import Foundation(veya geçişli Vakfı ithal başka modülü), senin döküm Arrayiçin NSArrayve birçok arama yöntemleri kullanabilirsiniz NSArray.


4

Bu çözümlerden herhangi biri benim için çalışıyor

Bu Swift 4 için sahip olduğum çözüm:

let monday = Day(name: "M")
let tuesday = Day(name: "T")
let friday = Day(name: "F")

let days = [monday, tuesday, friday]

let index = days.index(where: { 
            //important to test with === to be sure it's the same object reference
            $0 === tuesday
        })


2

Hala Swift 1.x'te çalışıyorsanız

o zaman dene,

let testArray = ["A","B","C"]

let indexOfA = find(testArray, "A") 
let indexOfB = find(testArray, "B")
let indexOfC = find(testArray, "C")

1

SWIFT 3 için basit bir işlev kullanabilirsiniz

func find(objecToFind: String?) -> Int? {
   for i in 0...arrayName.count {
      if arrayName[i] == objectToFind {
         return i
      }
   }
return nil
}

Bu sayı konumunu verecektir, böylece gibi kullanabilirsiniz

arrayName.remove(at: (find(objecToFind))!)

Yararlı olmayı umuyoruz


1

SWIFT 4

Diyelim ki cardButtons adlı diziden bir numarayı cardNumber'a kaydetmek istiyorsunuz, bunu şu şekilde yapabilirsiniz:

let cardNumber = cardButtons.index(of: sender)

gönderen düğmenizin adıdır


0

Hızlı 4

Referans türleri için:

extension Array where Array.Element: AnyObject {

    func index(ofElement element: Element) -> Int? {
        for (currentIndex, currentElement) in self.enumerated() {
            if currentElement === element {
                return currentIndex
            }
        }
        return nil
    }
}

0

Swift 4/5'de, bulma dizini için "firstIndex" kullanın.

let index = array.firstIndex{$0 == value}

0

Birinin bu problemi olması durumunda

Cannot invoke initializer for type 'Int' with an argument list of type '(Array<Element>.Index?)'

jsut bunu yap

extension Int {
    var toInt: Int {
        return self
    }
}

sonra

guard let finalIndex = index?.toInt else {
    return false
}

0

İçin (>= swift 4.0)

Oldukça basit. Aşağıdaki Arraynesneyi düşünün .

var names: [String] = ["jack", "rose", "jill"]

Öğenin dizinini elde etmek için rosetek yapmanız gereken:

names.index(of: "rose") // returns 1

Not:

  • Array.index(of:)döndürür Optional<Int>.

  • nil öğenin dizide bulunmadığını gösterir.

  • Döndürülen değeri zorla açmak veya if-letisteğe bağlı olarak dolaşmak için a'yı kullanmak isteyebilirsiniz.


0

Sadece firstIndex yöntemini kullanın.

array.firstIndex(where: { $0 == searchedItem })
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.