1

I am new to swift and looking for an efficient way to separate a string into an array based on regex matched.

In Ruby it is a one line command

irb(main):006:0> number = "(123) 456-7890"
=> "(123) 456-7890"
irb(main):007:0> number.scan(/(\w+)/).join()
=> "1234567890"
irb(main):008:0> 

In Swift, it was complicated and I used this function from an answer here Swift extract regex matches to separate the components into a String array. The join works the same way, so that's at least good. Is there a scan function in swift? If not, how can I create a global function that I can use.

func matchesForRegexInText(regex: String!, text: String!) -> [String] {

    let regex = NSRegularExpression(pattern: regex,
        options: nil, error: nil)!
    let nsString = text as NSString
    let results = regex.matchesInString(nsString as String,
        options: nil, range: NSMakeRange(0, nsString.length))
        as! [NSTextCheckingResult]
    return map(results) { nsString.substringWithRange($0.range)}
}

var number = "(123) (456) 7890"    
var wordArr = matchesForRegexInText("\\w+", number)
join("",wordArr) #> "1234567890"
Community
  • 1
  • 1
aarti
  • 2,815
  • 1
  • 23
  • 31
  • 1
    See [leave only numbers in a phone number in swift](http://stackoverflow.com/questions/29971505/leave-only-numbers-in-a-phone-number-in-swift) for various solutions. – Martin R May 02 '15 at 19:01
  • 1
    Your code looks somehow familiar: http://stackoverflow.com/a/27880748/1187415 :) – Martin R May 02 '15 at 19:41
  • Lol, it is your code thanks for letting me know, I have been all over stackoverflow learning this stuff and have that bookmarked, I should give you credit. – aarti May 02 '15 at 19:43
  • You might clarify what your actual question is. If you are asking *"Is there a built-in scan function in Swift like in Ruby"* then the answer is no. If your question is *"How can I remove all non-digits from a phone number"* then it is a duplicate of the question that I linked to. – Martin R May 02 '15 at 19:45
  • I will update the question, I am asking if there is a built in scan and if not how can I add it as an extension. – aarti May 02 '15 at 19:47
  • So your question is how to implement scan() as a String extension instead of a "free function"? – Martin R May 02 '15 at 19:53
  • I used your "free function" :) in several places and don't want to copy it around all the time. – aarti May 02 '15 at 19:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/76781/discussion-between-classyhacker-and-martin-r). – aarti May 02 '15 at 19:55

3 Answers3

2

String does not have a similar scan() method, but you can define one easily, using the same methods:

extension String {
    func scan(regex : String) -> [String] {
        let regex = NSRegularExpression(pattern: regex,
            options: nil, error: nil)!
        let nsString = self as NSString
        let results = regex.matchesInString(nsString as String,
            options: nil, range: NSMakeRange(0, nsString.length))
            as! [NSTextCheckingResult]
        return map(results) { nsString.substringWithRange($0.range)}
    }
}

Example:

let number = "(123) (456) 7890"
let wordArr = number.scan("\\w+")
println(wordArr) // [123, 456, 7890]

let digitsOnly = "".join(wordArr)
println(digitsOnly) // 1234567890
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
1

You can do:

let s = "(123) 456-7890"
let ns = s.stringByReplacingOccurrencesOfString(
    "\\D", withString: "", options: .RegularExpressionSearch)
//ns="1234567890"
dawg
  • 98,345
  • 23
  • 131
  • 206
1

update: Xcode 7.2 • Swift 2.1.1

extension String {
    var decimalDigits: String {
        return componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet()
            .invertedSet)
            .joinWithSeparator("")
    }
}

let inputString = "(123) 456-7890"   // "1234567890"
print(inputString.numbersOnly)   // "1234567890"
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571