Swift: Замена символов в строке — полный разбор для новичков

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Swift: Как заменить символы в строке? Полный разбор для начинающих

Рано или поздно каждый разработчик на Swift сталкивается с задачей: нужно заменить одни символы в строке на другие. Казалось бы, что может быть проще? Но новички часто теряются, потому что Swift String — это не массив символов, как в C, а сложная Unicode-совместимая структура. В этой статье мы разберём самые популярные и эффективные способы замены символов в Swift, от простых до продвинутых.

Мы не будем сухо перечислять методы. Вместо этого разберём реальные примеры, которые вы встретите в бою: от замены пробелов до удаления знаков препинания и работы с эмодзи. Поехали!

Почему Swift String — это не просто массив символов?

Прежде чем менять символы, важно понять, как устроена строка в Swift. String — это коллекция Character, но каждый Character может состоять из нескольких Unicode-скаляров (например, эмодзи 🚀 или буква «ё» с диакритикой). Поэтому индексация по Int здесь не работает напрямую. Вместо этого Swift использует String.Index.

Но для замены символов вам не нужно погружаться в дебри индексов — есть готовые высокоуровневые методы. Давайте посмотрим на самые популярные.

Метод №1: replacingOccurrences — король замены

Самый простой и очевидный способ — использовать метод replacingOccurrences(of:with:). Он возвращает новую строку с заменёнными вхождениями. Исходная строка остаётся неизменной (Swift — язык с иммутабельными строками по умолчанию).

let original = "Hello, World!"
let replaced = original.replacingOccurrences(of: "World", with: "Swift")
print(replaced) // "Hello, Swift!"
print(original) // "Hello, World!" — оригинал не изменился

Этот метод идеален для простых случаев: замена одного слова, символа или подстроки. Но что если нужно заменить несколько разных символов? Например, убрать все пробелы и точки?

Цепочка вызовов для множественных замен

Можно вызывать replacingOccurrences несколько раз подряд:

let text = "Hello, World! How are you?"
let cleaned = text
    .replacingOccurrences(of: ",", with: "")
    .replacingOccurrences(of: "!", with: "")
    .replacingOccurrences(of: " ", with: "_")
print(cleaned) // "Hello_World_How_are_you?"

Минус: если замен много, код становится громоздким. Для таких случаев лучше подходят другие методы или регулярные выражения.

Метод №2: Замена с помощью map и filter (функциональный подход)

Swift — это не только ООП, но и функциональное программирование. Вы можете пройтись по каждому символу строки с помощью map и заменить их по условию. Это особенно удобно, когда нужно заменить все вхождения определённого набора символов.

let input = "a1b2c3d4"
let result = input.map { char -> Character in
    if char.isNumber {
        return "X"
    } else {
        return char
    }
}
print(String(result)) // "aXbXcXdX"

Здесь мы заменили все цифры на "X". А если нужно удалить символы? Используйте filter:

let withPunctuation = "Hello!!! How are you??"
let noPunctuation = withPunctuation.filter { !$0.isPunctuation }
print(noPunctuation) // "Hello How are you"

Этот подход очень гибкий: вы можете использовать любые проверки — isNumber, isLetter, isWhitespace или даже сравнение с набором символов.

Метод №3: Регулярные выражения (NSRegularExpression)

Когда задача усложняется (замена по шаблону, удаление всех email, замена дат), без регулярных выражений не обойтись. Swift поддерживает NSRegularExpression из Foundation.

import Foundation

let text = "My email is test@example.com and your is user@test.org"
let regex = try! NSRegularExpression(pattern: "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}")
let replaced = regex.stringByReplacingMatches(
    in: text,
    range: NSRange(text.startIndex..., in: text),
    withTemplate: "[EMAIL]"
)
print(replaced) // "My email is [EMAIL] and your is [EMAIL]"

Обратите внимание: NSRegularExpression работает с NSRange, поэтому нужно конвертировать диапазон. Для простых строк это не проблема, но для сложных Unicode-строк (с эмодзи) могут быть нюансы. В Swift 5.7+ появился более удобный API — Regex, но он пока не так широко распространён.

Когда использовать regex, а когда нет?

  • replacingOccurrences — для замены конкретного слова или символа.
  • map/filter — для замены/удаления по типу символа (цифры, буквы, пунктуация).
  • NSRegularExpression — для сложных шаблонов (email, телефон, URL, повторяющиеся паттерны).

Метод №4: replaceSubrange — замена в конкретном месте

Иногда нужно заменить не все вхождения, а только символы в определённом диапазоне. Для этого используется replaceSubrange (но только если строка объявлена как var).

var greeting = "Hello, World!"
let range = greeting.index(greeting.startIndex, offsetBy: 7)..<greeting.endIndex
greeting.replaceSubrange(range, with: "Swift")
print(greeting) // "Hello, Swift"

Этот метод полезен, когда вы точно знаете позицию замены, но в реальных проектах используется реже, чем replacingOccurrences.

Практический пример: "Очистка" пользовательского ввода

Допустим, вы пишете приложение для ввода номера телефона. Пользователь может ввести "+7 (999) 123-45-67". Нужно оставить только цифры.

func cleanPhoneNumber(_ input: String) -> String {
    return input.filter { $0.isNumber }
}

let raw = "+7 (999) 123-45-67"
let cleaned = cleanPhoneNumber(raw)
print(cleaned) // "79991234567"

Одна строка кода — и готово! А если нужно заменить, например, все латинские буквы на строчные, а пробелы на дефисы для URL?

let title = "Swift Programming Guide"
let urlFriendly = title
    .lowercased()
    .replacingOccurrences(of: " ", with: "-")
print(urlFriendly) // "swift-programming-guide"

Производительность: что выбрать?

Для большинства задач разница в скорости незаметна. Но если вы обрабатываете миллионы строк (например, парсите лог-файлы), учитывайте:

  • replacingOccurrences — оптимизирован

Блоги

Рекомендаций по книгам