I am trying to find an item index
by searching a list
. Does anybody know how to do that?
I see there is list.StartIndex
and <
While indexOf()
works perfectly, it only returns one index.
I was looking for an elegant way to get an array of indexes for elements which satisfy some condition.
Here is how it can be done:
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)
In Swift 2 (with Xcode 7), Array
includes an indexOf method provided by the CollectionType protocol. (Actually, two indexOf
methods—one that uses equality to match an argument, and another that uses a closure.)
Prior to Swift 2, there wasn't a way for generic types like collections to provide methods for the concrete types derived from them (like arrays). So, in Swift 1.x, "index of" is a global function... And it got renamed, too, so in Swift 1.x, that global function is called find
.
It's also possible (but not necessary) to use the indexOfObject
method from NSArray
... or any of the other, more sophisticated search meth dis from Foundation that don't have equivalents in the Swift standard library. Just import Foundation
(or another module that transitively imports Foundation), cast your Array
to NSArray
, and you can use the many search methods on NSArray
.
If you are still working in Swift 1.x
then try,
let testArray = ["A","B","C"]
let indexOfA = find(testArray, "A")
let indexOfB = find(testArray, "B")
let indexOfC = find(testArray, "C")
For SWIFT 3 you can use a simple function
func find(objecToFind: String?) -> Int? {
for i in 0...arrayName.count {
if arrayName[i] == objectToFind {
return i
}
}
return nil
}
This will give the number position, so you can use like
arrayName.remove(at: (find(objecToFind))!)
Hope to be useful
In case somebody has this problem
Cannot invoke initializer for type 'Int' with an argument list of type '(Array<Element>.Index?)'
jsut do this
extension Int {
var toInt: Int {
return self
}
}
then
guard let finalIndex = index?.toInt else {
return false
}
tl;dr:
For classes, you might be looking for:
let index = someArray.firstIndex{$0 === someObject}
Full answer:
I think it's worth mentioning that with reference types (class
) you might want to perform an identity comparison, in which case you just need to use the ===
identity operator in the predicate closure:
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
Note that the above syntax uses trailing closures syntax, and is equivalent to:
let indexOfPerson1 = people.firstIndex(where: {$0 === person1})
Swift 4 / Swift 3 - the function used to be called index
Swift 2 - the function used to be called indexOf
* Note the relevant and useful comment by paulbailey about class
types that implement Equatable
, where you need to consider whether you should be comparing using ===
(identity operator) or ==
(equality operator). If you decide to match using ==
, then you can simply use the method suggested by others (people.firstIndex(of: person1)
).