Tôi biết rằng bạn muốn sử dụng CharacterSet
thay vì String
, nhưng CharacterSet
không (chưa, ít nhất) các ký tự hỗ trợ bao gồm nhiều hơn một Unicode.Scalar
. Xem ký tự "gia đình" () hoặc các ký tự cờ quốc tế (ví dụ: "" hoặc "") mà Apple đã trình bày trong cuộc thảo luận chuỗi trong video WWDC 2017 What's New in Swift. Biểu tượng cảm xúc nhiều tông màu da cũng thể hiện hành vi này (ví dụ: so với).
Do đó, tôi sẽ cảnh giác với việc sử dụng CharacterSet
(đây là "bộ giá trị ký tự Unicode để sử dụng trong hoạt động tìm kiếm"). Hoặc, nếu bạn muốn cung cấp phương pháp này để thuận tiện, hãy lưu ý rằng nó sẽ không hoạt động chính xác với các ký tự đại diện bởi nhiều vô hướng unicode.
Vì vậy, bạn có thể cung cấp một máy quét cung cấp cả CharacterSet
và String
lồng vào cốt của phương pháp skip
:
class MyScanner {
let string: String
var index: String.Index
init(_ string: String) {
self.string = string
index = string.startIndex
}
var remains: String { return String(string[index...]) }
/// Skip characters in a string
///
/// This rendition is safe to use with strings that have characters
/// represented by more than one unicode scalar.
///
/// - Parameter skipString: A string with all of the characters to skip.
func skip(charactersIn skipString: String) {
while index < string.endIndex, skipString.contains(string[index]) {
index = string.index(index, offsetBy: 1)
}
}
/// Skip characters in character set
///
/// Note, character sets cannot (yet) include characters that are represented by
/// more than one unicode scalar (e.g. or or). If you want to test
/// for these multi-unicode characters, you have to use the `String` rendition of
/// this method.
///
/// This will simply stop scanning if it encounters a multi-unicode character in
/// the string being scanned (because it knows the `CharacterSet` can only represent
/// single-unicode characters) and you want to avoid false positives (e.g., mistaking
/// the Jamaican flag, , for the Japanese flag,).
///
/// - Parameter characterSet: The character set to check for membership.
func skip(charactersIn characterSet: CharacterSet) {
while index < string.endIndex,
string[index].unicodeScalars.count == 1,
let character = string[index].unicodeScalars.first,
characterSet.contains(character) {
index = string.index(index, offsetBy: 1)
}
}
}
Vì vậy, ví dụ đơn giản của bạn vẫn sẽ làm việc:
let scanner = MyScanner("fizz buzz fizz")
scanner.skip(charactersIn: CharacterSet.alphanumerics)
scanner.skip(charactersIn: CharacterSet.whitespaces)
print(scanner.remains) // "buzz fizz"
Nhưng sử dụng String
hiển thị nếu các ký tự bạn muốn bỏ qua có thể bao gồm nhiều vô hướng unicode:
let family = "\u{200D}\u{200D}\u{200D}" //
let boy = ""
let charactersToSkip = family + boy
let string = boy + family + "foobar" // foobar
let scanner = MyScanner(string)
scanner.skip(charactersIn: charactersToSkip)
print(scanner.remains) // foobar
Như Michael Thác lưu ý trong các ý kiến dưới đây, CharacterSet
có một lỗi và thậm chí không xử lý 32-bit Unicode.Scalar
giá trị một cách chính xác, có nghĩa là nó thậm chí không xử lý nhân vật vô hướng đơn đúng nếu giá trị vượt quá 0xffff
(bao gồm biểu tượng cảm xúc, trong số những người khác). Tuy nhiên, các biểu hiện String
, ở trên, xử lý các chính xác.
Có một lớp hệ thống được gọi là 'NSScanner', được gắn vào Swift dưới dạng' Máy quét'. Bạn đã kiểm tra nó chưa? –
NSScanner chắc chắn trông giống như một bánh xe tôi đang tái phát minh lúc đầu đỏ mặt. Không điên về ngữ nghĩa của NS (sử dụng một tham số 'NSString?'), Nhưng nó có thể thực hiện thủ thuật. Vì tò mò, tôi đã xem qua [source] (https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/Scanner.swift), và nó chuyển đổi một 'String' thành một mảng' ', và đó là' bỏ qua 'chức năng sau đó chỉ sử dụng 'set.contains (UnicodeScalar (currentCharacter)!)'. –
PocketLogic
Nếu bạn không thích ngữ nghĩa NS của 'NSScanner', hãy sử dụng' Máy quét' của Foundation, không sử dụng các loại NS. Chắc chắn không xác định lớp của riêng bạn với tên của một lớp hiện có. Điều đó sẽ trở nên khó hiểu. – Rob