user11100093
user11100093

Reputation:

Get individual elements while matching a regex

I have a certain string given like so..

let string = "[@he man:user:123] [@super man:user:456] [@bat man:user:789]"

Now, I need an array containing just the name and the id. For that, I applied the following regex..

extension String {
  func findMentionText2() -> [[String]] {
    let regex = try? NSRegularExpression(pattern: "(@\\w+(?: \\w+)*):user:(\\w+)", options: [])
    if let matches = regex?.matches(in: self, options:[], range:NSMakeRange(0, self.count)) {
      return matches.map { match in
            return (1..<match.numberOfRanges).map {
                let rangeBounds = match.range(at: $0)
                guard let range = Range(rangeBounds, in: self) else {
                    return ""
                }
                return String(self[range])
            }
      }
   } else {
       return []
   }
 }
}

Now when I do let hashString = string.findMentionText() and print hashString, I get an array like so..

[["@he man", "123"], ["@super man", "456"], ["@bat man", "789"]]

So far so good..:)

Now I made a typealias and want to add it to an array.. So I did this...

 typealias UserTag = (name: String, id: String)

  var userTagList = [UserTag]()

and then,

let hashString2 = string.findMentionText2()

for unit in hashString2 {
  let user: UserTag = (name: unit.first!, id: unit.last!)
  userTagList.append(user)

}

for value in userTagList {
    print(value.id)
    print(value.name)
  }

Now here, instead of giving unit.first and unit.last in let user: UserTag = (name: unit.first!, id: unit.last!), want to add the name and id to the typealias as and when they are matched from the regex..ie.when I get the name or id, it should be added to the array instead of giving unit.first or unit.last..

How can I achieve that..?

Upvotes: 0

Views: 62

Answers (1)

rmaddy
rmaddy

Reputation: 318804

You just need to refactor your map to generate an array of UserTag instead of an array of string arrays. Here's one approach:

typealias UserTag = (name: String, id: String)

extension String {
    func findMentionText2() -> [UserTag] {
        let regex = try? NSRegularExpression(pattern: "(@\\w+(?: \\w+)*):user:(\\w+)", options: [])
        if let matches = regex?.matches(in: self, options:[], range:NSMakeRange(0, self.count)) {
            return matches.compactMap { match in
                if match.numberOfRanges == 3 {
                    let name = String(self[Range(match.range(at: 1), in:self)!])
                    let id = String(self[Range(match.range(at: 2), in:self)!])
                    return UserTag(name: name, id: id)
                } else {
                    return nil
                }
            }
        } else {
            return []
        }
    }
}

let string = "[@he man:user:123] [@super man:user:456] [@bat man:user:789]"
print(string.findMentionText2())

But I suggest you create a struct instead of using a tuple. It doesn't really change the implementation of findMentionText2 but using a struct lets you add other properties and methods as needed.

Upvotes: 1

Related Questions