Ответы:
Поскольку 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
протоколу.
ТЛ; др:
Для классов вы можете искать:
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
}
}
РЕДАКТИРОВАТЬ
В то время как мы на это, для удовольствия упражнения давайте расширим 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"]
Example1
let index = alphabets.firstIndex(where: {$0 == "A"})
Example2
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:
sequence.contains (element) : возвращает true, если заданная последовательность (например, массив) содержит указанный элемент.
Свифт 1:
Если вы просто хотите проверить, содержится ли элемент в массиве, то есть просто получите логический индикатор, используйте contains(sequence, element)
вместо find(array, element)
:
Содержит (sequence, 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
.index (где :) был изменен на .firstIndex (где :)
array.firstIndex(where: {$0 == "person1"})
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)
Или если вы хотите найти индекс на основе ключа из словаря. Здесь массив содержит объекты класса 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
Swift 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 Protocol, реализуйте метод lhs = rhs и только тогда вы можете использовать «.index (of». Например,
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 «index of» является глобальной функцией ... И она также переименована, так что в 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 для индексации массива как такового 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?)'
Просто сделай это
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
чтобы обойти необязательное.