Как находить элементы в массиве в программировании на Swift?

Как найти нужный элемент в массиве на Swift? Давайте разберемся! В этом руководстве вы узнаете, как использовать различные функции для поиска совпадающих элементов в массиве.

Поиск индекса элемента в массиве вручную

Прежде чем мы углубимся в способы поиска элементов в массиве, давайте выясним, как может работать такой алгоритм. Задача проста: для массива произвольного количества элементов нам нужно найти индекс заданного значения.

Вот обзор нашего подхода:

  • Перебрать каждое значение в массиве.
  • Отслеживать текущий индекс, который мы проверяем.
  • Сравните текущее значение со значением, которое мы ищем.
  • Если появляется совпадение, вернуть текущий индекс, если нет, продолжить перебор массива.
let names = ["Ford", "Arthur", "Trillian", "Zaphod", "Marvin", "Deep Thought", "Eddie", "Slartibartfast", "Humma Kuvula"]
 
let searchValue = "Zaphod"
var currentIndex = 0
 
for name in names {
    if name == searchValue {
        print("Имя \(name) для индекса \(currentIndex)")
        break
    }
 
    currentIndex += 1
}
 
// Имя Zaphod для индекса 3

Мы используем цикл for для перебора каждого элемента в массиве names.

  • С помощью оператора if мы проверяем, совпадает ли name с searchValue.
  • Если мы находим совпадение, мы выводим строку на консоль и останавливаем выполнение цикла с помощью break. Если мы этого не сделаем, цикл продолжится, даже если мы уже нашли то, что ищем.
  • В конце цикла мы увеличиваем значение currentIndex на единицу. Таким образом, мы отслеживаем текущий индекс массива.

Мы можем превратить наш код в функцию:

func find(value searchValue: String, in array: [String]) -> Int? {
    for (index, value) in array.enumerated() {
        if value == searchValue {
            return index
        }
    }
 
    return nil
}

Мы используем функцию enumerated() для получения пары индекс-значение. Таким образом, мы можем напрямую получить конкретный индекс для искомого элемента без необходимости отслеживать его самостоятельно.

Когда функция находит искомое значение, происходит выход из функции. Когда значение не может быть найдено, функция возвращает nil. Таким образом, возвращаемый тип функции — Int?

Мы можем использовать данную функцию следующим образом:

let names = ["Ford", "Arthur", "Trillian", "Zaphod", "Marvin", "Deep Thought", "Eddie", "Slartibartfast", "Humma Kuvula"]
 
let index = find(value: "Eddie", in: names)
print(index)
// Optional(6)

Поиск элемента в массиве с помощью firstIndex(of:)

Самый простой способ найти элемент в массиве — использовать функцию firstIndex(of:):

if let index = names.firstIndex(of: "Marvin") {
    print(index) 
}
// 4

Эта функция является универсальной, поэтому ее можно использовать независимо от типа массива.

Также мы можем заменить какое-либо значение в массиве:

if let index = names.firstIndex(of: "Zaphod") {
    names[index] = "Prostetnic Vogon Jeltz"
}

Поскольку функция firstIndex(of:) просматривает все значения массива от первого до последнего, она всегда возвращает индекс первого найденного совпадения. Если вы хотите получить последнее совпадение в массиве, вы можете использовать функцию lastIndex(of:).

Поиск элемента в массиве с помощью firstIndex(where:)

Что делать, если вы точно не знаете, какое конкретное значение ищете? Тут нам поможет функция firstIndex(where:). Эта функция принимает замыкание в качестве параметра для поиска совпадений в массиве.

let grades = [8, 9, 10, 1, 2, 5, 3, 4, 8, 8]
 
if let index = grades.firstIndex(where: { $0 < 7 }) {
    print("Первый индекс < 7 = \(index)")
}
 
// 3

В приведенном выше коде мы работаем с массивом целых чисел grades. Мы хотим знать индекс первого элемента массива, который меньше 7. При этом мы знаем только то, что оно должно быть меньше 7.

Код между фигурными скобками — это замыкание, которое выполняется для каждого элемента массива, пока мы не найдем успешное совпадение, то есть выражение $0 < 7 должно вернуть true.

Мы используем опциональное связывание для извлечения опционального значения из firstIndex(where:).

Данная функция принадлежит к группе функций, которые могут выбирать элементы из массива, соответствующие заданному предикату:

  • firstIndex(where:) возвращает индекс первого элемента, соответствующего предикату.
  • lastIndex(where:) возвращает индекс последнего элемента, соответствующего предикату.
  • contains(where:) возвращает логическое значение, указывающее, содержит ли массив элемент, соответствующий предикату.
  • allSatisfy(_:) возвращает логическое значение, указывающее, все ли элементы в массиве соответствуют предикату.
  • first(where:)возвращает первый элемент (не индекс) массива, который соответствует предикату.
  • last(where:)возвращает последний элемент (не индекс) массива, который соответствует предикату.

Имейте в виду, что если вы хотите использовать вышеуказанные функции, элементы в вашем массиве должны соответствовать протоколу Equatable. Типы, соответствующие этому протоколу, можно сравнить с помощью оператора ==, который используется для проверки равенства двух элементов.

Поиск всех элементов в массиве с помощью all(where:)

Что, если мы хотим найти все элементы в массиве, которые бы соответствовали заданному предикату? В стандартной библиотеке Swift пока нет данной функции, но мы можем создать свою собственную.

extension Array where Element: Equatable {
    func all(where predicate: (Element) -> Bool) ->; [Element]  {
        return self.compactMap { predicate($0) ? $0 : nil }
    }
}

Объявление функции принимает параметр типа (Element) -> Bool и возвращает массив типа [Element]. Далее мы используем функцию compactMap (_ :). Эта функция применяет замыкание для каждого элемента в массиве, а также удаляет значения nil. Выражение predicate($0) ? $0 : nil вернет значение $0, когда предикат возвращает true и nil, когда будет возвращено false.

let grades = [8, 9, 10, 1, 2, 5, 3, 4, 8, 8]
let goodGrades = grades.all(where: { $0 > 7 })
print(goodGrades) 
// [8, 9, 10, 8, 8]
Читайте также:
Добавить комментарий

Ваш адрес email не будет опубликован.