Chris G.
Chris G.

Reputation: 25974

Swift 3.1 Get a range between two char?

I am clearly doing something wrong, because this has newer taken me so long to do the following:(Playground code beneath).

Note: Swift 3.1 ~

I am just trying to get 123 out from piz(123)zazz

let aString = "piz(123)zazz"

let startBracket: Character = "("
if let idx1 = aString.characters.index(of: startBracket) {
    let pos1 = aString.characters.distance(from: aString.startIndex, to: idx1)
    print("Found \(startBracket) at position \(pos1)")
}
else {
    print("Not found")
}

let endBracket: Character = ")"
if let idx2 = aString.characters.index(of: endBracket) {
    let pos2 = aString.characters.distance(from: aString.startIndex, to: idx2)
    print("Found \(startBracket) at position \(pos2)")
}
else {
    print("Not found")
}

let range = pos1..<pos2 // << this is not working, I give up!!!

let result_1 = aString.substring(with: range)

Upvotes: 2

Views: 1489

Answers (2)

vadian
vadian

Reputation: 285092

It's much easier:

  • The start index is the upperBound of the range of ( in the string

  • The end index is the lowerBound of the range of ) in the string

      let aString = "piz(123)zazz"
    
      if let openParenthesisRange = aString.range(of: "("),
          let closeParenthesisRange = aString.range(of: ")", range: openParenthesisRange.upperBound..<aString.endIndex) {
    
          let range = openParenthesisRange.upperBound..<closeParenthesisRange.lowerBound
          let result = aString.substring(with: range)
          print(result)
      }
      else {
          print("Not found")
      }
    

Alternatively regular expression, it's more code but it's much more versatile

let string = "piz(123)zazz"

let pattern = #"\((\d+)\)"# // searches for 0 ore more digits between parentheses

do {
    let regex = try NSRegularExpression(pattern: pattern)
    if let match = regex.firstMatch(in: string, range: NSRange(string.startIndex..., in: string)) {
        let range = match.rangeAt(1)
        let start = string.index(string.startIndex, offsetBy: range.location)
        let end = string.index(start, offsetBy: range.length)
        print(string.substring(with: start..<end))
    } else {
        print("Not Found")
    }
} catch {
    print("Regex Error:", error)
}

Upvotes: 6

Rahul
Rahul

Reputation: 2100

Your pos1 and pos2 are out of scope when you are trying to use. They both have been defined inside of an if block and their scope ends there itself.

I would suggest declaring them on the top to have them in scope.

 let aString = "piz(123)zazz"
 let pos1: Int?  // You don't need optional here but I prefer it 
 let pos2: Int? 
 .
 .
 .
 if let p1 = pos1, p2 = pos2  { // Optional Chaining
     let range = pos1..<pos2
 }

Upvotes: 3

Related Questions