Превратите функцию Swift в расширение для повторного использования

#swift

Вопрос:

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

Как это можно превратить в расширение?

 var string = "11224B"
let removeCharacters: Set<Character> = [" ", ";", ".", "!", "/"]
string.removeAll(where: { removeCharacters.contains($0) })
print(string)
 

Ответ №1:

Что вам нужно, так это расширить протокол, который требует, чтобы вы реализовали метод removeAll(где:), в данном случае RangeReplaceableCollection и ограничили себя StringProtocol :


 extension RangeReplaceableCollection where Self: StringProtocol {
    mutating func remove(characters: Set<Element>) {
        removeAll(where: characters.contains)
    }
}
 

 var string = "1/1!2.2;4 B"
string.remove(characters: [" ", ";", ".", "!", "/"])
print(string)  // "11224Bn"
 

И метод без мутирования также, но вместо этого используется фильтр. Вам просто нужно вернуться Self :

 extension RangeReplaceableCollection where Self: StringProtocol {
    func removing(characters: Set<Element>) -> Self {
        filter { !characters.contains($0) }
    }
}
 

 let string = "1/1!2.2;4 B"
string.removing(characters: [" ", ";", ".", "!", "/"]) // "11224Bn"
 

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


 extension RangeReplaceableCollection where Self: StringProtocol {
    mutating func remove<S: Sequence>(characters: S) where S.Element == Element {
        removeAll(where: characters.contains)
    }
    func removing<S: Sequence>(characters: S) -> Self where S.Element == Element {
        filter { !characters.contains($0) }
    }
}
 

 var string = "1/1!2.2;4 B"
let characters: Set<Character> = [" ", ";", ".", "!", "/"]
string.remove(characters: characters) 
string // "11224Bn"
 

 let string = "1/1!2.2;4 B"
let charactersString = " ;.!/"
string.removing(characters: charactersString) // "11224Bn"
 

Комментарии:

1. Лео, можно ли также удалить все смайлики? Как можно добавить представление isEmojiPresentation в массив символов для удаления?

2. @MarkLyson просто отфильтруйте их filter { $0.unicodeScalars.first?.properties.isEmojiPresentation == false } , если вы хотите удалить символы в последовательности, а также любой символ, который является присутствием filter { !characters.contains($0) amp;amp; $0.unicodeScalars.first?.properties.isEmojiPresentation == false }

Ответ №2:

Расширение:

 extension String {
    func removeCharacters(from characterSet: CharacterSet) -> String {
        let filteredString = self.unicodeScalars.filter { !characterSet.contains($0) }
        return String(String.UnicodeScalarView(filteredString))
    }
}
 

Использование:

 var string1 = "1122 ;4B"
print(string1.removeCharacters(from: [" ", ";", ".", "!", "/"]))
 

Использовать removeCharacters в качестве параметра по умолчанию:

 extension String {
    func removeCharacters(from characterSet: CharacterSet = [" ", ";", ".", "!", "/"]) -> String {
        let filteredString = self.unicodeScalars.filter { !characterSet.contains($0) }
        return String(String.UnicodeScalarView(filteredString))
    }
}

var string1 = "1122 ;4B"
print(string1.removeCharacters())
 

Комментарии:

1. Может removeCharacters быть, внутри расширения? Было бы лучше, если бы удаляемые персонажи не восстанавливались каждый раз

2. Да, положи removeCharacters внутрь func , если ты этого хочешь.

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

4. @MarkLyson обновил ответ. Проверьте это.

5. Еще лучше, чтобы функция принимала параметр набора символов со значением по умолчанию «нормальный», который требуется оператору. Таким образом, вам не нужно указывать набор символов, если он не отличается от обычного набора.