0

So what I am trying to achieve:

I have an input string that looks like this:

let inputString = "1*1 (10, 10) (5, 5)"

Note the space after the first digit within the brackets.

To separate this input, I am using:

inputString.components(separatedBy: " ")

Which returns the following array:

0: 1*1

1 "(10,"

2 "10)"

3 "(5,"

4: "5)"

Where as the result I want is:

0: "1*1"

1: "(10, 10)"

2: "(5, 5)"

The issue is that the space within the coordinate is causing the string to separate again, when I don't want it to.

I have also tried to separate them using:

inputString.replacingOccurrences(of: " ", with: "").components(separatedBy: CharacterSet.init(charactersIn: "\"([{)")).filter({ $0 != "" })

But this removes the "(" and ")" from the strings, which I need to keep.

Any suggestions would be welcome. Thanks

Liam
  • 429
  • 1
  • 13
  • 33

1 Answers1

0

Without regex

You can split with ( and ) and get odd chunks back while wrapping them with parentheses. You may re-use the code from :

let inputString = "1*1 (10, 10) (5, 5)"
let newArr = inputString.components(separatedBy: ["(", ")"])

var finalArr = [String]()

for (index, value) in newArr.enumerated() {

    if (index + 1) % 2 == 1 {
        finalArr.append(contentsOf: value.components(separatedBy: " ").filter { $0 != "" })
    }
    else {
        finalArr.append("(\(value))")
    }
}
print(finalArr)
// => ["1*1", "(10, 10)", "(5, 5)"]

With regex

You can match one or more occurrences of any substring inside parentheses or any char other than whitespace and parentheses:

import Foundation

func matches(for regex: String, in text: String) -> [String] {
  do {
        let regex = try NSRegularExpression(pattern: regex)
        let results = regex.matches(in: text,
                                    range: NSRange(text.startIndex..., in: text))
        return results.map {
            String(text[Range($0.range(at: 0), in: text)!])
        }
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}
let originalString = "1*1 (10, 10) (5, 5)"
print(matches(for: #"(?:\([^()]*\)|[^()\s])+"#, in: originalString))
// => ["1*1", "(10, 10)", "(5, 5)"]

See the regex demo. Details:

  • (?: - start of a non-capturing group:
    • \( - a ( char
    • [^()]* - zero or more chars other than ( and )
    • \) - a ) char
  • | - or
    • [^()\s] - any char other than (, ) and whitespace
  • )+ - end of the group, one or more occurrences.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563