Відповіді:
Оскільки swift в деяких аспектах є більш функціональним, ніж орієнтованим на об'єкти (а масиви - це структури, а не об'єкти), використовуйте функцію "find" для роботи над масивом, який повертає необов'язкове значення, тому будьте готові обробляти нульове значення:
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({$0 > 5}) // 5
let indexOfFirstGreaterThanOneHundred = arr2.indexOf({$0 > 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
indexOf
масив структур, який ви самі визначили, ваша структура повинна відповідати Equatable
протоколу.
tl; dr:
Для занять ви можете шукати:
let index = someArray.firstIndex{$0 === someObject}
Повна відповідь:
Я думаю, що варто згадати, що з посилальними типами ( class
) ви можете виконати порівняння ідентичності , і в цьому випадку вам просто потрібно використовувати ===
оператор ідентичності при закритті предиката:
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
Зауважимо, що вищевказаний синтаксис використовує синтаксис із завершенням закриття та еквівалентний:
let indexOfPerson1 = people.firstIndex(where: {$0 === person1})
Swift 4 / Swift 3 - функція, яку раніше використовували index
Swift 2 - функція, яку раніше викликали indexOf
* Зверніть увагу на актуальний і корисний коментар по paulbailey про class
типах , які реалізують Equatable
, де ви повинні розглянути , чи слід вам порівняння з використанням ===
( тотожний оператора) або ==
( рівність оператора). Якщо ви вирішили відповідати використанню ==
, то ви можете просто скористатися методом, запропонованим іншими ( people.firstIndex(of: person1)
).
Person
реалізований Equatable
протокол, це не знадобиться.
Binary operator '===' cannot be applied to operands of type '_' and 'Post'
, Post
моя структура ... які - або ідеї?
structs
(і enums
) - цінні типи, а не посилання. Тільки еталонні типи (наприклад class
) мають логіку порівняння ідентичності ( ===
). Ознайомтеся з іншими відповідями, що робити з цим structs
(в основному ви просто використовуєте array.index(of: myStruct)
, переконуючись, що тип myStruct
відповідає Equatable
( ==
)).
Ви можете filter
мати масив із закриттям:
var myList = [1, 2, 3, 4]
var filtered = myList.filter { $0 == 3 } // <= returns [3]
І ви можете порахувати масив:
filtered.count // <= returns 1
Таким чином, ви можете визначити, чи містить масив ваш елемент, комбінуючи такі:
myList.filter { $0 == 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
}
}
EDIT
Хоча ми це робимо, для цікавої вправи продовжимо, 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 { $0 == 3 }
// returns the index position of 3 or nil if not found
Array
щоб мати find
метод, який робить те, що ви хочете. Я ще не знаю, чи це хороша практика, але це акуратний експеримент.
enumerate
щоб він більше не застосовувався, але ви абсолютно праві.
func firstIndex(of element: Element) -> Int?
var alphabets = ["A", "B", "E", "D"]
Приклад1
let index = alphabets.firstIndex(where: {$0 == "A"})
Приклад2
if let i = alphabets.firstIndex(of: "E") {
alphabets[i] = "C" // i is the index
}
print(alphabets)
// Prints "["A", "B", "C", "D"]"
Хоча indexOf()
працює чудово, він повертає лише один індекс.
Я шукав елегантний спосіб отримати масив індексів для елементів, які задовольняють певній умові.
Ось як це можна зробити:
Швидкий 3:
let array = ["apple", "dog", "log"]
let indexes = array.enumerated().filter {
$0.element.contains("og")
}.map{$0.offset}
print(indexes)
Швидкий 2:
let array = ["apple", "dog", "log"]
let indexes = array.enumerate().filter {
$0.element.containsString("og")
}.map{$0.index}
print(indexes)
Для користувацького класу потрібно реалізувати протокол 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)
Оновлення для Swift 2:
row.contains (елемент) : Повертає true, якщо задана послідовність (наприклад, масив) містить зазначений елемент.
Швидкий 1:
Якщо ви шукаєте просто перевірити, чи міститься елемент всередині масиву, тобто просто отримайте булевий індикатор, використовуйте contains(sequence, element)
замість find(array, element)
:
містить (послідовність, елемент) : Повертає істину, якщо задана послідовність (наприклад, масив) містить зазначений елемент.
Дивіться приклад нижче:
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
.index (де :) було змінено на .firstIndex (де :)
array.firstIndex(where: {$0 == "person1"})
Швидкий 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)
Або Якщо ви хочете знайти індекс на основі ключа від словника. Тут масив містить об'єкти класу Model, і я збігаю властивість 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
Швидкий 2.1
var array = ["0","1","2","3"]
if let index = array.indexOf("1") {
array.removeAtIndex(index)
}
print(array) // ["0","2","3"]
Швидкий 3
var array = ["0","1","2","3"]
if let index = array.index(of: "1") {
array.remove(at: index)
}
array.remove(at: 1)
let array
? Використання self
також сумнівно.
У Swift 4 , якщо ви проїжджаєте через масив DataModel, переконайтеся, що ваша модель даних відповідає протоколу Equatable, застосуйте метод lhs = rhs і лише тоді ви можете використовувати ".index (з". Наприклад
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)
У Swift 2 (з Xcode 7) Array
включений indexOf
спосіб, передбачений CollectionType
протоколом. (Насправді, два indexOf
методи - один, який використовує рівність для узгодження аргументу, та інший, який використовує закриття.)
До Swift 2 не було можливості для загальних типів, таких як колекції, запропонувати методи для конкретних типів, похідних від них (наприклад, масиви). Так, у Swift 1.x "індекс" - це глобальна функція ... І він також був перейменований, тому в Swift 1.x ця глобальна функція називається find
.
Також можливо (але не обов’язково) використовувати indexOfObject
метод від NSArray
... або будь-якого іншого, більш досконалого пошукового методу від Foundation, який не має еквівалентів у стандартній бібліотеці Swift. Просто import Foundation
(або інший модуль , який імпортує транзитивно Foundation), відлитий ваші Array
до NSArray
, і ви можете використовувати безліч методів пошуку на NSArray
.
Будь-яке з цього рішення працює для мене
Це рішення, яке у мене є для 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
})
Ви також можете використовувати функціональну бібліотеку Dollar, щоб зробити indexOf на масиві як такому 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 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
Скажімо, ви хочете зберегти число з масиву під назвою cardButtons у cardNumber, ви можете це зробити так:
let cardNumber = cardButtons.index(of: sender)
відправник - це назва вашої кнопки
У Swift 4/5 використовуйте "firstIndex" для пошуку індексу.
let index = array.firstIndex{$0 == value}
У випадку, якщо хтось має цю проблему
Cannot invoke initializer for type 'Int' with an argument list of type '(Array<Element>.Index?)'
jsut зроби це
extension Int {
var toInt: Int {
return self
}
}
тоді
guard let finalIndex = index?.toInt else {
return false
}
Для (>= swift 4.0)
Це досить просто. Розглянемо наступний Array
об’єкт.
var names: [String] = ["jack", "rose", "jill"]
Для того, щоб отримати індекс елемента rose
, все, що вам потрібно зробити, це:
names.index(of: "rose") // returns 1
Примітка:
Array.index(of:)
повертає Optional<Int>
.
nil
означає, що елемент не присутній у масиві.
Ви можете змусити відкрутити повернене значення або використовувати, if-let
щоб обійти необов'язковий.