Как найти индекс элемента списка в Swift?

Я пытаюсь найти item index путем поиска list. Кто-нибудь знает, как это сделать?

Я вижу, что есть list.StartIndex и list.EndIndex, но я хочу что-то вроде python list.index("text").

Ответ 1

Поскольку быстрота в некоторых отношениях более функциональна, чем объектно-ориентированная (а массивы - это структуры, а не объекты), используйте функцию "find" для работы с массивом, которая возвращает необязательное значение, поэтому будьте готовы обрабатывать значение nil:

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

Ответ 2

ТЛ; др:

Для классов вы можете искать:

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

* Обратите внимание на релевантный и полезный комментарий Паулбейли о типах class которые реализуют Equatable, где вам нужно Equatable, следует ли сравнивать, используя === (оператор тождества) или == (оператор равенства). Если вы решите сопоставить, используя ==, тогда вы можете просто использовать метод, предложенный другими (people.firstIndex(of: person1)).

Ответ 3

Вы можете 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

Ответ 4

Swift 5

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"]"

Ответ 5

Пока indexOf() работает отлично, он возвращает только один индекс.

Я искал элегантный способ получить массив индексов для элементов, которые удовлетворяют некоторому условию.

Вот как это можно сделать:

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)

Ответ 6

Для настраиваемого класса вам необходимо реализовать протокол 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)

Ответ 7

Обновление для Swift 2:

sequence.contains(element): возвращает 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.   
}

Ответ 8

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")
}

Ответ 9

В 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), NSArray свой Array в NSArray, и вы можете использовать множество методов поиска в NSArray.

Ответ 10

В 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)

Ответ 11

Любое из этого решения работает для меня

Это решение для 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 the same object reference
            $0 === tuesday
        })

Ответ 12

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)

Ответ 13

Вы также можете использовать функциональную библиотеку Dollar для создания indexOf в массиве как http://www.dollarswift.org/#indexof-indexof

$.indexOf([1, 2, 3, 1, 2, 3], value: 2) 
=> 1

Ответ 14

Если вы все еще работаете в Swift 1.x

затем попробуйте

let testArray = ["A","B","C"]

let indexOfA = find(testArray, "A") 
let indexOfB = find(testArray, "B")
let indexOfC = find(testArray, "C")

Ответ 15

Для 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))!)

Надеюсь быть полезным

Ответ 16

SWIFT 4

Допустим, вы хотите сохранить число из массива с именем cardButtons в cardNumber, вы можете сделать это следующим образом:

let cardNumber = cardButtons.index(of: sender)

отправитель имя вашей кнопки

Ответ 17

в Swift 4.2

.index (где :) был изменен на .firstIndex (где :)

array.firstIndex(where: {$0 == "person1"})

Ответ 18

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
    }
}

Ответ 19

Например, если у нас был массив чисел:

let numbers = [2, 4, 6, 8, 9, 10]

Мы могли бы найти первое нечетное число, как это:

let firstOdd = numbers.index { $0 % 2 == 1 }

Это вернет 4 в качестве необязательного целого числа, потому что первое нечетное число (9) находится в индексе четыре.

Ответ 20

В Swift 4/5 используйте "firstIndex" для поиска индекса.

let index = array.firstIndex{$0 == value}