Site icon AppTractor

Знакомимся с пакетом Swift Algorithms

Почти каждое приложение, которое я создавал и поддерживал, включает пакет Swift Algorithms. Однако я заметил, что только некоторые разработчики знакомы с ним. Сегодня мы узнаем, что пакет Swift Algorithms предлагает нам для написания более качественного и безопасного кода для сложных алгоритмов.

Зачем

Конечно, вы можете переписать любой алгоритм из пакета Swift Algorithms самостоятельно, но в этом случае вам придется поддерживать и тестировать его. С другой стороны, вы можете положиться на готовый к использованию пакет, который можно включить в каждое приложение, над которым вы работаете, без дублирования кода и быть уверенным, что члены сообщества хорошо протестировали его.

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

Установка

Сначала необходимо добавить пакет в проект на экране настроек проекта Xcode. На вкладке «Package Dependencies» можно добавить или удалить любой необходимый пакет. Пакет Swift Algorithms есть на GitHub, где вы можете легко следить за обновлениями, просматривать запросы и отслеживать проблемы.

Пакет Swift Algorithms содержит множество ценных алгоритмов для работы с коллекциями и последовательностями. Охватить их в рамках одного поста практически невозможно, но я расскажу о своих любимых.

Бинарный поиск

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

Как вы, наверное, знаете, бинарный поиск — лучший способ найти элемент в отсортированном массиве данных. Обычно мы запрашиваем HealthKit отсортированные данные, что позволяет нам эффективно использовать бинарный поиск. Бинарный поиск требует, чтобы данные были отсортированы по искомому ключу.

let someDate = Date.now
let index = heartRates.partitioningIndex { $0.startDate >= someDate }

guard
    index != heartRates.endIndex,
    heartRates[index].startDate == someDate
else {
    return nil
}

return heartRates[index]

Пакет Swift Algorithms предоставляет функцию partitioningIndex, обобщенную версию двоичного поиска. Она использует ту же логику, что и бинарный поиск.

Однако вместо возврата элемента она возвращает индекс первого элемента, разделяя вашу коллекцию на две части, где любой элемент из первой части возвращает false для вашего предиката, а любой элемент из второй части всегда возвращает true для того же предиката.

Мы должны обернуть его результаты дополнительным защитным оператором, проверяющим их. Если функция partitioningIndex не может найти соответствующий индекс, она возвращает конец коллекции.

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

Разбиение на части

Разбиение коллекции на части — еще одна распространенная задача в моих приложениях. Вам может понадобиться разделить коллекцию на куски любого количества или с помощью дополнительной логики. Пакет Swift Algorithms предоставляет нам API для разбиения на части именно для этого случая.

let numbers = [1, 2, 3, 4, 5, 6]
print(numbers.chunks(ofCount: 2))
// [1, 2]
// [3, 4]
// [5, 6]

Пакет Swift Algorithms предоставляет функцию chunks, которая принимает в качестве параметра количество элементов в одной части и возвращает массив подпоследовательностей.

В моем приложении сложилась более интересная ситуация, в которой особая логика должна управлять функцией chunking. В моем случае мне нужны куски, в которых элементы имеют временные интервалы между собой не более одного часа.

sleepSamples.chunked { $1.startDate.timeIntervalSince($0.endDate) < 3600 }

Как вы можете видеть в примере выше, мы используем функцию chunked с предикатом, где мы можем сравнить два соседних элемента коллекции и решить, когда мы хотим поместить их в одну и ту же часть.

Фильтрация

Почти в каждом приложении возникает ситуация, когда у вас есть коллекция с необязательными значениями, и вам нужно сохранить только значения, не являющиеся нулями. Для этого случая в пакете Swift Algorithms представлены функции compacted.

let array: [Int?] = [10, nil, 30, nil, 2, 3, nil, 5]
let withNoNils = array.compacted()
// Array(withNoNils) == [10, 30, 2, 3, 5]

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

let numbers = [1, 2, 3, 3, 2, 3, 3, 2, 2, 2, 1]
let unique = numbers.uniqued()
// Array(unique) == [1, 2, 3]

Семплирование

Еще одна ситуация, с которой я столкнулся в своих приложениях — это извлечение некоторого количества минимальных или максимальных элементов из коллекции. Вы можете легко сделать это с помощью функций min, max или minAndMax пакета Swift Algorithms.

let numbers = [7, 1, 6, 2, 8, 3, 9]
let smallestThree = numbers.min(count: 3)
// [1, 2, 3]

let numbers = [7, 1, 6, 2, 8, 3, 9]
let largestThree = numbers.max(count: 3)
// [7, 8, 9]

А если вам нужно получать некоторое количество случайных элементов из коллекции? В пакете Swift Algorithms есть функция randomSample, принимающая в качестве единственного параметра count и возвращающая массив случайных элементов.

let numbers = [7, 1, 6, 2, 8, 3, 9]
let randomNumbers = numbers.randomSample(count: 3)

Комбинации

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

let colors = ["fuchsia", "cyan", "mauve", "magenta"]
for combo in colors.combinations(ofCount: 3) {
    print(combo.joined(separator: ", "))
}
// fuchsia, cyan, mauve
// fuchsia, cyan, magenta
// fuchsia, mauve, magenta
// cyan, mauve, magenta

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

Заключение

Сегодня мы открыли лишь видимую часть айсберга Swift Algorithms. Нам предстоит узнать еще много нового, и я рекомендую вам изучить документацию по пакету и заменить им свою собственную реализацию. Надеюсь, вам понравился этот пост.

Спасибо, что прочитали!

Источник

Exit mobile version