atineoSE
atineoSE

Reputation: 4107

Matching strings in Swift where characters are different but contain equal Unicode scalars

I want to match a string with a regex in Swift. I am following the approach described here.

Typically this would work like this (as evaluated in a Xcode playground):

var str1 = "hello"
var str2 = "bye"
var regex1 = "[abc]"
str1.rangeOfString(regex1, options:.RegularExpressionSearch) != nil // false - there is no match
str2.rangeOfString(regex1, options:.RegularExpressionSearch) != nil // true - there is a match

So far so good. Now let us take two strings which contain characters consisting of more than one Unicode scalar like so (as evaluated in a Xcode playground):

var str3 = "✔️"
var regex2 = "[✖️]"
"✔️" == "✖️" // false - the strings are not equal
str3.rangeOfString(regex2, options:.RegularExpressionSearch) != nil // true - there is a match!

I wouldn't expect a match when I try to find "✖️" in "✔️", but because "\u{2714}"+"\u{FE0F}" == "✔️" and "\u{2716}"+"\u{FE0F}" == "✖️", then "\u{FE0F}" is found in both and that gives a match.

How would you perform the match?

Upvotes: 2

Views: 597

Answers (1)

atineoSE
atineoSE

Reputation: 4107

Digging into the link provided by @stribizhev I have come up with this (as evaluated in Xcode playground):

var str1 = "hello"
var str2 = "bye"
var str3 = "✔️"
var regex1 = "[abc]"
var regex2 = "[✖️]"

let matcher1 = try! NSRegularExpression(pattern: regex1, options: NSRegularExpressionOptions.CaseInsensitive)
let matcher2 = try! NSRegularExpression(pattern: regex2, options: NSRegularExpressionOptions.CaseInsensitive)

matcher1.numberOfMatchesInString(str1, options: NSMatchingOptions.ReportCompletion, range: NSMakeRange(0, str1.characters.count)) != 0 // false - does not match
matcher1.numberOfMatchesInString(str2, options: NSMatchingOptions.ReportCompletion, range: NSMakeRange(0, str2.characters.count)) != 0 // true - matches
matcher2.numberOfMatchesInString(str3, options: NSMatchingOptions.ReportCompletion, range: NSMakeRange(0, str3.characters.count)) != 0 // false - does not match

This is for XCode 7.1 and Swift 2.1

Upvotes: 1

Related Questions