How to Compare Range<String.Index> and Defaultbidirectionalindices<String.Characterview>

How to compare Range String.Index and DefaultBidirectionalIndices String.CharacterView ?

From SE-0065 – A New Model for Collections and Indices

In Swift 2, collection.indices returned a Range<Index>, but because a range is a simple pair of indices and indices can no longer be advanced on their own, Range<Index> is no longer iterable.

In order to keep code like the above working, Collection has acquired an associated Indices type that is always iterable, ...

Since rangeOfComposedCharacterSequence returns a range of
character indices, the solution is not to use indices, but
startIndex..<endIndex:

myString.rangeOfComposedCharacterSequence(at: myString.startIndex) 
== myString.startIndex..<myString.endIndex

inout String is not convertible to String in Swift 3 range

In Swift 3, indices property has become a Collection of Index, and not any more a sort of Range. If you want a Range of Index representing the whole String, you need to write something like this:

let myModifiedString = myOriginalString.replacingOccurrences(of: "#(?:\\S+)\\s?",
with: "",
options: .regularExpression,
range: myOriginalString.startIndex..<myOriginalString.endIndex)

how do I properly express this 'rangeOfCharacter' statement using swift 3?

You just need to use ..< operator to create your range. Note: If you want to check the whole string you can omit the options and range parameters.

if let _ = string.rangeOfCharacter(from: invalidCharacters, options: [], range: string.startIndex..<string.endIndex) {

}

Or simply:

if let _ = string.rangeOfCharacter(from: invalidCharacters) {

}

How can I remove or replace all punctuation characters from a String?

Xcode 11.4 • Swift 5.2 or later

extension StringProtocol {
var words: [SubSequence] {
split(whereSeparator: \.isLetter.negation)
}
}


extension Bool {
var negation: Bool { !self }
}


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


How to know if two emojis will be displayed as one emoji?

Update for Swift 4 (Xcode 9)

As of Swift 4, a "Emoji sequence" is treated as a single grapheme
cluster (according to the Unicode 9 standard):

let s = "ab‍❤️‍‍br>print(s.count) // 4

so the other workarounds are not needed anymore.


(Old answer for Swift 3 and earlier:)

A possible option is to enumerate and count the
"composed character sequences" in the string:

let s = "ab‍❤️‍‍br>var count = 0
s.enumerateSubstringsInRange(s.startIndex..<s.endIndex,
options: .ByComposedCharacterSequences) {
(char, _, _, _) in
if let char = char {
count += 1
}
}
print(count) // 4

Another option is to find the range of the composed character
sequences at a given index:

let s = "‍❤️‍‍br>if s.rangeOfComposedCharacterSequenceAtIndex(s.startIndex) == s.characters.indices {
print("This is a single composed character")
}

As String extension methods:

// Swift 2.2:
extension String {
var composedCharacterCount: Int {
var count = 0
enumerateSubstringsInRange(characters.indices, options: .ByComposedCharacterSequences) {
(_, _, _, _) in count += 1
}
return count
}

var isSingleComposedCharacter: Bool {
return rangeOfComposedCharacterSequenceAtIndex(startIndex) == characters.indices
}
}

// Swift 3:
extension String {
var composedCharacterCount: Int {
var count = 0
enumerateSubstrings(in: startIndex..<endIndex, options: .byComposedCharacterSequences) {
(_, _, _, _) in count += 1
}
return count
}

var isSingleComposedCharacter: Bool {
return rangeOfComposedCharacterSequence(at: startIndex) == startIndex..<endIndex
}
}

Examples:

".composedCharacterCount // 1
".characters.count // 2

"‍❤️‍‍.composedCharacterCount // 1
"‍❤️‍‍.characters.count // 4

".composedCharacterCount // 2
".characters.count // 1

As you see, the number of Swift characters (extended grapheme clusters) can be more or less than
the number of composed character sequences.



Related Topics



Leave a reply



Submit