Как найти индекс элемента списка в Swift?
Я пытаюсь найти индекс элемента, выполнив поиск в списке. Кто-нибудь знает, как это сделать?
Я вижу, что есть список.StartIndex и список.EndIndex bu я хочу что-то вроде списка python.index ("text")
16 ответов
поскольку swift в некоторых отношениях более функциональен, чем объектно-ориентированный (а массивы-это структуры, а не объекты), используйте функцию "найти" для работы с массивом, которая возвращает необязательное значение, поэтому будьте готовы обрабатывать нулевое значение:
let arr:Array = ["a","b","c"]
find(arr, "c")! // 2
find(arr, "d") // nil
обновление для Swift 2.0:
старый find
функция больше не поддерживается с Swift 2.0!
С Swift 2.0, Array
получает способность найти индекс элемент, использующий функцию, определенную в расширении CollectionType
(где Array
реализует):
let arr = ["a","b","c"]
let indexOfA = arr.indexOf("a") // 0
let indexOfB = arr.indexOf("b") // 1
let indexOfD = arr.indexOf("d") // nil
кроме того, поиск первого элемента в массиве, выполняющем предикат, поддерживается другим расширением CollectionType
:
let arr2 = [1,2,3,4,5,6,7,8,9,10]
let indexOfFirstGreaterThanFive = arr2.indexOf({ > 5}) // 5
let indexOfFirstGreaterThanOneHundred = arr2.indexOf({ > 100}) // nil
обратите внимание, что эти две функции возвращают необязательные значения, как find
раньше.
обновление для Swift 3.0:
обратите внимание, что синтаксис indexOf изменился. Для изделий, соответствующих Equatable
вы можете использовать:
let indexOfA = arr.index(of: "a")
подробную документацию по методу можно найти по адресу https://developer.apple.com/reference/swift/array/1689674-index
для элементов массива, которые не соответствуют Equatable
вам понадобится 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:
С Swift 4.2,index
больше не используется, но разделен на firstIndex
и lastIndex
для лучшего разъяснения. Так в зависимости от того, ищете ли вы первый или последний индекс элемента:
let arr = ["a","b","c","a"]
let indexOfA = arr.firstIndex(of: "a") // 0
let indexOfB = arr.lastIndex(of: "a") // 3
я думаю, стоит упомянуть, что со ссылочными типами (class
) вы можете выполнить личность сравнение, в таком случае вам просто нужно использовать ===
оператор идентификации в закрытии предиката:
Swift 3 / Swift 4:
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.index{ === person1} // 0
let indexOfPerson2 = people.index{ === person2} // 1
let indexOfPerson3 = people.index{ === person3} // 2
let indexOfPerson4 = people.index{ === person4} // nil
обратите внимание, что приведенный выше синтаксис использует синтаксис замыкания и эквивалентен:
let indexOfPerson1 = people.index(where: { === person1})
Свифт 2 - в index
синтаксис функции:
let indexOfPerson1 = people.indexOf{ === person1}
* обратите внимание на соответствующие и полезные комментарий by paulbailey о class
типы, которые реализуют Equatable
, где вам нужно рассмотреть, следует ли сравнивать использование ===
(личность оператора) или ==
(равенство оператор). Если вы решите сопоставить с помощью ==
, то вы можете просто использовать метод, предложенный другим (people.index(of: person1)
).
вы можете filter
массив с замком:
var myList = [1, 2, 3, 4]
var filtered = myList.filter { == 3 } // <= returns [3]
и вы можете подсчитать массив:
filtered.count // <= returns 1
таким образом, вы можете определить если массив включает в себя ваш элемент, объединив их:
myList.filter { == 3 }.count > 0 // <= returns true if the array includes 3
если вы хотите найти позицию, я не вижу другой способ, но вы можете определенно сделать это так:
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
}
}
редактировать
пока мы на нем, для забавного упражнения давайте расширим Array
иметь find
способ:
extension Array {
func find(includedElement: T -> Bool) -> Int? {
for (idx, element) in enumerate(self) {
if includedElement(element) {
return idx
}
}
return nil
}
}
теперь мы можем сделать это:
myList.find { == 3 }
// returns the index position of 3 or nil if not found
пока indexOf()
работает, он возвращает только один индекс.
Я искал элегантный способ получить массив индексов для элементов, которые удовлетворяют некоторому условию.
вот как это можно сделать:
Swift 3:
let array = ["apple", "dog", "log"]
let indexes = array.enumerated().filter {
.element.contains("og")
}.map{.offset}
print(indexes)
Swift 2:
let array = ["apple", "dog", "log"]
let indexes = array.enumerate().filter {
.element.containsString("og")
}.map{.index}
print(indexes)
для пользовательского класса необходимо реализовать эквивалентный протокол.
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)
обновление для Swift 2:
последовательности.содержит(элемент): возвращает true, если заданная последовательность (например массив) содержит указанный элемент.
Swift 1:
Если вы хотите просто проверить, содержится ли элемент внутри массива, то есть просто получить логический индикатор, используйте contains(sequence, element)
вместо find(array, element)
:
содержит(последовательность, элемент): Возвращает true, если заданная последовательность (например массив) содержит указанный элемент.
см. пример ниже:
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.
}
Swift 4.2
func index(of element: Element) -> Int?
var alphabets = ["A", "B", "E", "D"]
Пример1
let index = alphabets.index(where: { == "A"})
Пример 2
if let i = alphabets.index(of: "E") {
alphabets[i] = "C" // i is the index
}
print(alphabets)
// Prints "["A", "B", "C", "D"]"
в Swift 2 (с Xcode 7), Array
включает в себя indexOf
метод CollectionType
протокол. (На самом деле, два indexOf
методы-тот, который использует равенство, чтобы соответствовать аргументу, и другое это использует закрытие.)
до Swift 2 не было способа для универсальных типов, таких как коллекции, предоставлять методы для конкретных типов, производных от них (например, массивов). Итак, в Swift 1.x, "индекс" является глобальной функцией... И он также был переименован, поэтому в Swift 1.x, эта глобальная функция называется find
.
также возможно (но не обязательно) использовать indexOfObject
метод NSArray
... или любой другой, более сложный поисковый мет из фонда, который не имеет эквивалентов в стандартной библиотеке Swift. Просто import Foundation
(или другой модуль, который транзитивно импортирует Foundation), бросьте свой Array
до NSArray
, и вы можете использовать многие методы поиска на NSArray
.
на Swift 4, если вы проходите через массив DataModel, убедитесь , что ваша модель данных соответствует эквивалентному протоколу , реализуйте метод lhs=rhs, и только тогда вы можете использовать ".индекс(компании" . Например
class Photo : Equatable{
var imageURL: URL?
init(imageURL: URL){
self.imageURL = imageURL
}
static func == (lhs: Photo, rhs: Photo) -> Bool{
return lhs.imageURL == rhs.imageURL
}
}
и
let index = self.photos.index(of: aPhoto)
вы также можете использовать функциональную библиотеку Dollar для индексации массива как такового http://www.dollarswift.org/#indexof-indexof
$.indexOf([1, 2, 3, 1, 2, 3], value: 2)
=> 1
Если вы все еще работаете в Swift 1.x
затем попробуйте
let testArray = ["A","B","C"]
let indexOfA = find(testArray, "A")
let indexOfB = find(testArray, "B")
let indexOfC = find(testArray, "C")
Swift 2.1
var array = ["0","1","2","3"]
if let index = array.indexOf("1") {
array.removeAtIndex(index)
}
print(array) // ["0","2","3"]
Swift 3
var array = ["0","1","2","3"]
if let index = array.index(of: "1") {
array.remove(at: index)
}
array.remove(at: 1)
это решение работает для меня
Это решение у меня для 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
=== tuesday
})
Swift 4. Если Ваш массив содержит элементы типа [String: AnyObject]. Поэтому, чтобы найти индекс элемента, используйте следующий код
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)
или если вы хотите найти индекс на основе ключей из словаря. Здесь массив содержит объекты класса модели, и я сопоставляю свойство 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")
}
для SWIFT 3 Вы можете использовать простую функцию
func find(objecToFind: String?) -> Int? {
for i in 0...arrayName.count {
if arrayName[i] == objectToFind {
return i
}
}
return nil
}
это даст номер позиции, так что вы можете использовать как
arrayName.remove(at: (find(objecToFind))!)
надеюсь быть полезным
Swift 4
для ссылочных типов:
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
}
}