Как удалить или заменить все знаки пунктуации из строки?

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

Например, если у меня есть что-то вроде

var words = "Hello, this : is .. a  string?"

Я хотел бы иметь возможность создавать массив с

"[Hello, this, is, a, string]"

Моя первоначальная мысль заключалась в том, чтобы использовать что-то вроде words.stringByTrimmingCharactersInSet() для удаления любых символов, которые я не хотел, но это могло бы занять только символы.

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

for letter in words {
    if NSCharacterSet.punctuationCharacterSet.characterIsMember(letter){
        //remove that character from the string
    }
}

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

Ответ 1

Xcode 10.2 • Swift 5 или новее

extension StringProtocol {
    var words: [SubSequence] {
        return split{ !$0.isLetter }
    }
}

let sentence = "Hello, this : is .. a  string?"
let words = sentence.words  // ["Hello", "this", "is", "a", "string"]

Ответ 2

String имеет метод enumerateSubstringsInRange(). С опцией .ByWords он определяет границы слов и пунктуация автоматически:

Swift 3/4:

let string = "Hello, this : is .. a \"string\"!"
var words : [String] = []
string.enumerateSubstrings(in: string.startIndex..<string.endIndex,
                                  options: .byWords) {
                                    (substring, _, _, _) -> () in
                                    words.append(substring!)
}
print(words) // [Hello, this, is, a, string]

Swift 2:

let string = "Hello, this : is .. a \"string\"!"
var words : [String] = []
string.enumerateSubstringsInRange(string.characters.indices,
    options: .ByWords) {
        (substring, _, _, _) -> () in
        words.append(substring!)
}
print(words) // [Hello, this, is, a, string]

Ответ 3

Это работает с Xcode 8.1, Swift 3:

Сначала определите расширение общего назначения для фильтрации с помощью CharacterSet:

extension String {
  func removingCharacters(inCharacterSet forbiddenCharacters:CharacterSet) -> String 
{
    var filteredString = self
    while true {
      if let forbiddenCharRange = filteredString.rangeOfCharacter(from: forbiddenCharacters)  {
        filteredString.removeSubrange(forbiddenCharRange)
      }
      else {
        break
      }
    }

    return filteredString
  }
}

Затем фильтруйте с помощью пунктуации:

let s:String = "Hello, world!"
s.removingCharacters(inCharacterSet: CharacterSet.punctuationCharacters) // => "Hello world"

Ответ 4

Способ NSScaner:

let words = "Hello, this : is .. a  string?"

//
let scanner = NSScanner(string: words)
var wordArray:[String] = []
var word:NSString? = ""

while(!scanner.atEnd) {
  var sr = scanner.scanCharactersFromSet(NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKMNOPQRSTUVWXYZ"), intoString: &word)
  if !sr {
    scanner.scanLocation++
    continue
  }
  wordArray.append(String(word!))
}

println(wordArray)

Ответ 5

Альтернативный способ фильтрации символов из набора и получения массива слов - это методы массива filter и reduce. Это не так компактно, как другие ответы, но показывает, как один и тот же результат можно получить по-другому.

Сначала определите массив удаляемых символов:

let charactersToRemove = Set(Array(".:?,"))

next преобразует входную строку в массив символов:

let arrayOfChars = Array(words)

Теперь мы можем использовать reduce для построения строки, полученной добавлением элементов из arrayOfChars, но пропуская все те, что включены в charactersToRemove:

let filteredString = arrayOfChars.reduce("") {
    let str = String($1)
    return $0 + (charactersToRemove.contains($1) ? "" : str)
}

Это создает строку без знаков пунктуации (как определено в charactersToRemove).

Последние 2 шага:

разделите строку на массив слов, используя пустой символ в качестве разделителя:

let arrayOfWords = filteredString.componentsSeparatedByString(" ")

last, удалите все пустые элементы:

let finalArrayOfWords = arrayOfWords.filter { $0.isEmpty == false }

Ответ 6

let charactersToRemove = NSCharacterSet.punctuationCharacterSet().invertedSet
let aWord = "".join(words.componentsSeparatedByCharactersInSet(charactersToRemove))