Возможно ли безопасно использовать индекс одного Array для доступа к другому Array того же размера?
Нет. Индекс принадлежит конкретной коллекции и не становится безопасным для другой коллекции только потому, что у них одинаковый тип, размер или одинаковые числовые индексы.
У Array индекс обычно имеет тип Int, поэтому ошибочное использование может случайно сработать. Однако обобщённый код не должен полагаться на это: индекс нужно получать у той коллекции, к которой он применяется.
Протокол Collection не связывает позицию элемента с целым числом. Разные коллекции могут использовать разные типы индексов, а индекс может содержать больше информации, чем простой offset.
Такой подход позволяет поддерживать коллекции с нелинейными или составными индексами и не заставляет алгоритмы заранее копировать элементы в массив. Поэтому Swift рассматривает индекс как часть состояния конкретной коллекции, а не как универсальный номер позиции.
Наивный код может сохранить индекс одного массива, затем применить его к другому массиву того же размера. Для Array это часто выглядит рабочим, поскольку оба индекса являются целыми числами.
Но для другой реализации Collection тот же тип индекса может обозначать другую позицию или вообще быть недействительным. Кроме того, мутация коллекции может инвалидировать ранее сохранённые индексы. Ошибка проявится либо как неверный элемент, либо как нарушение предусловия во время доступа.
Индекс следует получать и использовать в контексте одной и той же коллекции. Безопасный вариант — передавать сам индекс вместе с коллекцией, для которой он был создан, либо вычислять позицию заново на целевой коллекции.
Даже одинаковый Index не даёт гарантии переносимости между экземплярами. В обобщённом алгоритме нужно использовать startIndex, endIndex, index(_:offsetBy:) и другие операции самой целевой коллекции, а не предполагать, что индекс — это числовой offset.
Индекс также нельзя безоговорочно сохранять после мутации коллекции. Правила его действительности зависят от конкретного типа коллекции и операции; безопасная стратегия — не использовать индекс после потенциально инвалидирующей мутации, если документация типа не даёт соответствующей гарантии.
В обработчике найден индекс элемента в одном массиве, а затем разработчик пытается применить его к отфильтрованной копии. Вариант с прямым переиспользованием индекса прост, но хрупок: копия может иметь другую структуру, а в обобщённом коде индекс вообще может быть несовместимым.
Вариант с хранением целого offset устойчив только для случайно подходящих коллекций и может иметь неверную стоимость или смысл для произвольного Collection. Вариант с повторным вычислением индекса на целевой коллекции требует дополнительного шага, но сохраняет корректность и переносимость.
Поэтому для библиотечного или обобщённого кода выбирают последний вариант. В результате алгоритм не зависит от внутреннего представления индексов и не ломается при замене Array на другую коллекцию.
Нет гарантии, что такое сравнение имеет содержательный результат. Даже если тип Index поддерживает Comparable, это не означает, что индексы из разных экземпляров коллекции можно сопоставлять. Сравнивать и комбинировать следует индексы, полученные из одной коллекции.
На практике одинаковые значения Array могут использовать совместное хранилище благодаря copy-on-write, но это не превращает индекс в универсальный объект. Контракт Collection требует рассматривать индекс в связи с коллекцией, из которой он получен; переносимость между экземплярами нельзя закладывать в обобщённый алгоритм.
Нужно переносить не индекс, а смысл позиции: например, ключ элемента, идентификатор или вычисленный offset, если такая модель действительно подходит. Затем на целевой коллекции следует получить новый индекс через её собственные операции и отдельно обработать случай, когда соответствующая позиция или элемент отсутствует.