简体   繁体   中英

Getting a empty Range<String.Index> in Swift

I am very new to Swift and have trying to use regular expressions, but getting the match from the string seems to be an insurmountable task.

This is my current approach.

print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression))))

This doesn't work because

Value of optional type 'Range<String.Index>?' must be unwrapped to a value of type 'Range<String.Index>'

I guess this has something to do with it possibly being null, so now i want to provide it with an alternative using the?? operator.

print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression)?? Range<String.Index>())))

What i want to do is to provide it with an empty range object but it seems to be impossible to create an empty object of the type required.

Any suggestions?

There is simply no argument-less initialiser for Range<String.Index> .

One way you can create an empty range of String.Index is to use:

data.startIndex..<data.startIndex

Remember that you shouldn't use integers here, because we are dealing with indices of a string . See this if you don't understand why.

So:

print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression) ?? data.startIndex..<data.startIndex)))

But substring(with:) is deprecated. You are recommended to use the subscript:

print(data[data.range(of: "[a-zA-Z]at", options: .regularExpression) ?? data.startIndex..<data.startIndex])

Instead of trying to create an empty range, I would suggest creating an empty Substring in case there was no match. Range can be quite error-prone, so using this approach you can save yourself a lot of headaches.

let match: Substring
if let range = data.range(of: "[a-zA-Z]at", options: .regularExpression) {
    match = data[range]
} else {
    match = ""
}
print(match)

You can create such constructor with a simple extension to Range type. Like this:

extension Range where Bound == String.Index {
    static var empty: Range<Bound> {
        "".startIndex..<"".startIndex
    }

    init() {
        self = Range<Bound>.empty
    }
}

Then it can be used like this:

let str = "kukukukuku"
let substr1 = str[str.range(of: "abc", options: .regularExpression) ?? Range<String.Index>()]
let substr2 = str[str.range(of: "abc", options: .regularExpression) ?? Range<String.Index>.empty]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM