Ответ вслух Middle Коллекции и строки обновлено

Как устроены строки в Swift

Вопрос

Почему работа со строками в Swift сложнее, чем в других языках, и как это обходить?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Swift честен к Unicode: Character это расширенный графемный кластер, то, что пользователь видит как один символ. Флаг или буква с диакритикой могут занимать несколько скаляров и байтов.

Что должно прозвучать в ответе

  • `Character` это графемный кластер, длина в памяти разная

  • Индексация через `String.Index`, а не `Int`; `count` O(n)

  • Представления `utf8`, `utf16`, `unicodeScalars` для разных задач

  • `Substring` разделяет память с исходной строкой

  • Для частого доступа по номеру преобразовать в `Array(s)` или работать с `utf8`

  • Нативное хранение в UTF-8 с Swift 5

Что могут спросить следом

  • Как правильно передать диапазон строки в API с NSRange?
  • Почему "é" == "e\u{301}" даёт true?

Разбор

Swift честен к Unicode: Character это расширенный графемный кластер, то, что пользователь видит как один символ. Флаг или буква с диакритикой могут занимать несколько скаляров и байтов. Поэтому у строки нет индекса по Int: такой сабскрипт выглядел бы как O(1), а стоил бы O(n). Индексы это String.Index, и count тоже требует прохода. Для разных задач есть представления: utf8 для байтов и быстрого парсинга, utf16 для совместимости с NSString, unicodeScalars для работы со скалярами. Строки сравниваются по канонической эквивалентности, поэтому разные записи «é» равны. Срезы это Substring, они не копируют данные, но держат исходник, так что для хранения я перевожу их в String. На собесе, если задача на символы, я сразу делаю Array(s) или работаю с utf8, чтобы иметь O(1) доступ.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.