Odpowiedzi:
Ponieważ szybkie jest pod pewnymi względami bardziej funkcjonalne niż obiektowe (a tablice są strukturami, a nie obiektami), użyj funkcji „znajdź”, aby operować na tablicy, która zwraca wartość opcjonalną, więc przygotuj się na obsługę wartości zerowej:
let arr:Array = ["a","b","c"]
find(arr, "c")! // 2
find(arr, "d") // nil
Aktualizacja dla Swift 2.0:
Stara find
funkcja nie jest już obsługiwana w Swift 2.0!
Dzięki Swift 2.0 Array
zyskuje możliwość znalezienia indeksu elementu za pomocą funkcji zdefiniowanej w rozszerzeniu CollectionType
(który Array
implementuje):
let arr = ["a","b","c"]
let indexOfA = arr.indexOf("a") // 0
let indexOfB = arr.indexOf("b") // 1
let indexOfD = arr.indexOf("d") // nil
Ponadto znalezienie pierwszego elementu w tablicy spełniającej predykat jest obsługiwane przez inne rozszerzenie 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
Zauważ, że te dwie funkcje zwracają wartości opcjonalne, tak find
jak wcześniej.
Aktualizacja dla Swift 3.0:
Uwaga: zmieniono składnię indexOf. Do przedmiotów zgodnych Equatable
możesz użyć:
let indexOfA = arr.index(of: "a")
Szczegółowa dokumentacja metody znajduje się na stronie https://developer.apple.com/reference/swift/array/1689674-index
W przypadku elementów tablicy, które nie są zgodne Equatable
, musisz użyć index(where:)
:
let index = cells.index(where: { (item) -> Bool in
item.foo == 42 // test if this is the item you're looking for
})
Aktualizacja dla Swift 4.2:
W Swift 4.2 index
nie jest już używany, ale jest podzielony na firstIndex
i lastIndex
dla lepszego wyjaśnienia. W zależności od tego, czy szukasz pierwszego czy ostatniego indeksu przedmiotu:
let arr = ["a","b","c","a"]
let indexOfA = arr.firstIndex(of: "a") // 0
let indexOfB = arr.lastIndex(of: "a") // 3
indexOf
z tablicy struktur, które sam zdefiniowałeś, Twoja struktura musi być zgodna z Equatable
protokołem.
tl; dr:
Na zajęcia możesz szukać:
let index = someArray.firstIndex{$0 === someObject}
Pełna odpowiedź:
Myślę, że warto wspomnieć, że w przypadku typów referencyjnych ( class
) można wykonać porównanie tożsamości , w takim przypadku wystarczy użyć ===
operatora tożsamości w zamknięciu predykatu:
Swift 5, Swift 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
Zauważ, że powyższa składnia używa końcowej składni zamknięć i jest równoważna z:
let indexOfPerson1 = people.firstIndex(where: {$0 === person1})
Swift 4 / Swift 3 - wywoływana funkcja index
Swift 2 - wywoływana funkcja indexOf
* Zwróć uwagę na odpowiedni i użyteczny komentarz autorstwa paulbailey na temat class
typów, które się implementują Equatable
, gdzie musisz rozważyć, czy powinieneś porównywać używając ===
( operator tożsamości ) czy ==
( operator równości ). Jeśli zdecydujesz się dopasować za pomocą ==
, możesz po prostu użyć metody sugerowanej przez innych ( people.firstIndex(of: person1)
).
Person
zaimplementowania Equatable
protokołu nie byłoby to konieczne.
Binary operator '===' cannot be applied to operands of type '_' and 'Post'
, Post
moja struct ... jakiś pomysł?
structs
(i enums
) są typami wartości, a nie typami referencyjnymi. Tylko typy referencyjne (np. class
) Mają logikę porównywania tożsamości ( ===
). Sprawdź inne odpowiedzi, aby dowiedzieć się, co z tym zrobić structs
(w zasadzie po prostu używasz array.index(of: myStruct)
, upewniając się, że typ myStruct
jest zgodny z Equatable
( ==
)).
Możesz filter
tablicę z zamknięciem:
var myList = [1, 2, 3, 4]
var filtered = myList.filter { $0 == 3 } // <= returns [3]
I możesz policzyć tablicę:
filtered.count // <= returns 1
Możesz więc ustalić, czy tablica zawiera Twój element, łącząc te:
myList.filter { $0 == 3 }.count > 0 // <= returns true if the array includes 3
Jeśli chcesz znaleźć pozycję, nie widzę wymyślnego sposobu, ale na pewno możesz to zrobić w następujący sposób:
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
}
}
EDYTOWAĆ
Skoro już to robimy, dla zabawy wykonajmy Array
jeszcze jedną find
metodę:
extension Array {
func find(includedElement: T -> Bool) -> Int? {
for (idx, element) in enumerate(self) {
if includedElement(element) {
return idx
}
}
return nil
}
}
Teraz możemy to zrobić:
myList.find { $0 == 3 }
// returns the index position of 3 or nil if not found
Array
aby mieć find
metodę, która robi to, co chcesz. Nie wiem jeszcze, czy to dobra praktyka, ale to fajny eksperyment.
enumerate
nie był już stosowany, ale masz całkowitą rację.
func firstIndex(of element: Element) -> Int?
var alphabets = ["A", "B", "E", "D"]
Przykład 1
let index = alphabets.firstIndex(where: {$0 == "A"})
Przykład 2
if let i = alphabets.firstIndex(of: "E") {
alphabets[i] = "C" // i is the index
}
print(alphabets)
// Prints "["A", "B", "C", "D"]"
Chociaż indexOf()
działa idealnie, zwraca tylko jeden indeks.
Szukałem eleganckiego sposobu na uzyskanie tablicy indeksów dla elementów, które spełniają pewne warunki.
Oto jak to zrobić:
Swift 3:
let array = ["apple", "dog", "log"]
let indexes = array.enumerated().filter {
$0.element.contains("og")
}.map{$0.offset}
print(indexes)
Swift 2:
let array = ["apple", "dog", "log"]
let indexes = array.enumerate().filter {
$0.element.containsString("og")
}.map{$0.index}
print(indexes)
W przypadku klasy niestandardowej należy zaimplementować protokół Equatable.
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)
Aktualizacja dla Swift 2:
sekwencji.contains (element) : Zwraca wartość true, jeśli dana sekwencja (na przykład tablica) zawiera określony element.
Swift 1:
Jeśli chcesz tylko sprawdzić, czy element jest zawarty w tablicy, to po prostu weź wskaźnik boolean, użyj contains(sequence, element)
zamiast find(array, element)
:
zawiera (sekwencja, element) : Zwraca wartość true, jeśli dana sekwencja (na przykład tablica) zawiera określony element.
Zobacz przykład poniżej:
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.
}
w Swift 4.2
.index (gdzie :) został zmieniony na .firstIndex (gdzie :)
array.firstIndex(where: {$0 == "person1"})
Swift 4. Jeśli tablica zawiera elementy typu [String: AnyObject]. Aby znaleźć indeks elementu, użyj poniższego kodu
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)
Lub Jeśli chcesz znaleźć indeks na podstawie klucza ze słownika. Tutaj tablica zawiera obiekty klasy Model i dopasowuję właściwość id.
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
Swift 2.1
var array = ["0","1","2","3"]
if let index = array.indexOf("1") {
array.removeAtIndex(index)
}
print(array) // ["0","2","3"]
Szybki 3
var array = ["0","1","2","3"]
if let index = array.index(of: "1") {
array.remove(at: index)
}
array.remove(at: 1)
let array
? Zastosowanie self
jest również wątpliwe.
W Swift 4 , jeśli przemierzasz tablicę DataModel, upewnij się, że Twój model danych jest zgodny z protokołem Equatable, zaimplementuj metodę lhs = rhs, a dopiero potem możesz użyć „.index (z”. Na przykład
class Photo : Equatable{
var imageURL: URL?
init(imageURL: URL){
self.imageURL = imageURL
}
static func == (lhs: Photo, rhs: Photo) -> Bool{
return lhs.imageURL == rhs.imageURL
}
}
I wtedy,
let index = self.photos.index(of: aPhoto)
W Swift 2 (z Xcode 7) Array
zawiera indexOf
metodę dostarczoną przez CollectionType
protokół. (Właściwie dwie indexOf
metody - jedna używa równości w celu dopasowania argumentu, a druga używa zamknięcia.)
Przed wersją Swift 2 typy ogólne, takie jak kolekcje, nie zapewniały metod dla konkretnych typów pochodnych (takich jak tablice). Tak więc w Swift 1.x „indeks” jest funkcją globalną… I również zmieniono jego nazwę, więc w Swift 1.x ta funkcja globalna nazywa sięfind
.
Możliwe jest również (ale nie konieczne) użycie indexOfObject
metody z NSArray
... lub dowolnej innej, bardziej wyrafinowanej metody wyszukiwania z Foundation, która nie ma odpowiedników w standardowej bibliotece Swift. Po prostu import Foundation
(lub inny moduł, który tranzytowo importuje Foundation), prześlij swój Array
naNSArray
, i możesz korzystać z wielu metod wyszukiwania NSArray
.
Każde z tych rozwiązań działa dla mnie
To rozwiązanie mam dla Swift 4:
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
})
Możesz także użyć biblioteki funkcjonalnej Dollar do wykonania indeksu dla tablicy jako takiej http://www.dollarswift.org/#indexof-indexof
$.indexOf([1, 2, 3, 1, 2, 3], value: 2)
=> 1
Jeśli nadal pracujesz w Swift 1.x
więc spróbuj,
let testArray = ["A","B","C"]
let indexOfA = find(testArray, "A")
let indexOfB = find(testArray, "B")
let indexOfC = find(testArray, "C")
W SWIFT 3 możesz użyć prostej funkcji
func find(objecToFind: String?) -> Int? {
for i in 0...arrayName.count {
if arrayName[i] == objectToFind {
return i
}
}
return nil
}
To da numer pozycji, więc możesz użyć like
arrayName.remove(at: (find(objecToFind))!)
Mam nadzieję, że się przydadzę
SWIFT 4
Załóżmy, że chcesz zapisać liczbę z tablicy o nazwie cardButtons w cardNumber, możesz to zrobić w ten sposób:
let cardNumber = cardButtons.index(of: sender)
nadawca to nazwa twojego przycisku
W Swift 4/5 użyj „firstIndex” do znalezienia indeksu.
let index = array.firstIndex{$0 == value}
W przypadku, gdy ktoś ma ten problem
Cannot invoke initializer for type 'Int' with an argument list of type '(Array<Element>.Index?)'
jsut zrób to
extension Int {
var toInt: Int {
return self
}
}
następnie
guard let finalIndex = index?.toInt else {
return false
}
Dla (>= swift 4.0)
To raczej bardzo proste. Rozważ następujący Array
obiekt.
var names: [String] = ["jack", "rose", "jill"]
Aby uzyskać indeks elementu rose
, wystarczy:
names.index(of: "rose") // returns 1
Uwaga:
Array.index(of:)
zwraca an Optional<Int>
.
nil
oznacza, że element nie jest obecny w tablicy.
Możesz wymusić rozpakowanie zwróconej wartości lub użyć opcji, if-let
aby obejść opcję opcjonalną.