5

Basically, I want to make a program where if you start typing a name, the app will recognize it from the database and fill in the name for you. To do this, if a person types a comma after finishing a name, the app will start recording what the next name is. If it matches as a substring of one of the names in the database, it will fill it in for the user. The issue is that I need to get what part of the name has been filled out so far after the last occurrence of the comma character in the textField string, but I don't know how. For example: User types: "Daniel, Joh" And the app fills in John for you. Thanks.

4 Answers 4

4

If you really want the characters after the last comma, you could use a regular expression:

let string = "Hamilton, A"
let regex = try! NSRegularExpression(pattern: ",\\s*(\\S[^,]*)$")
if let match = regex.firstMatch(in: string, range: string.nsRange), let result = string[match.range(at: 1)] {
    // use `result` here
}

Where, in Swift 4:

extension String {

    /// An `NSRange` that represents the full range of the string.

    var nsRange: NSRange {
        return NSRange(startIndex ..< endIndex, in: self)
    }

    /// Substring from `NSRange`
    ///
    /// - Parameter nsRange: `NSRange` within the string.
    /// - Returns: `Substring` with the given `NSRange`, or `nil` if the range can't be converted.

    subscript(nsRange: NSRange) -> Substring? {
        return Range(nsRange, in: self)
            .flatMap { self[$0] }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Does the regex solution also work if there are more than 2 names on the list?
Sorry I'm just asking because it says firstMatchInString not last. Thanks
OK, I understand the confusion. But if you look at my regex string, the last character is a $, which says "match for the end of the string". Thus, you'll get only one match, the one at the end (if any). I only use firstMatchInString because, since we're only getting the last one, there's no need to enumerate through, but rather just grab the "first" match at the end of the string.
3

Many thanks to Rob. We can even extend his String extension by including the full answer to the initial question, with any Character:

extension String {

func substringAfterLastOccurenceOf(_ char: Character) -> String {

    let regex = try! NSRegularExpression(pattern: "\(char)\\s*(\\S[^\(char)]*)$")
    if let match = regex.firstMatch(in: self, range: self.nsRange), let result = self[match.range(at: 1)] {
        return String(result)
    }
    return ""
}

// ... Rob's String extension 

}

So we just need to call:

let subStringAfterLastComma = "Hamilton, A".substringAfterLastOccurenceOf(",")

2 Comments

Not working any more: Value of type 'String' has no member 'nsRange'
@PaulSpiesberger you need to include rob's extension too, then it will work
1

Simple solution with range(of and options regularExpression and backwards.

It searches for a comma followed by an optional whitespace character.

extension String {
    var subStringAfterLastComma : String {
        guard let subrange = self.range(of: ",\\s?", options: [.regularExpression, .backwards]) else { return self }
        return String(self[subrange.upperBound...])
    }
}

let string1 = "Dan".subStringAfterLastComma // "Dan"
let string2 = "Daniel, Joh".subStringAfterLastComma // "Joh"

Comments

1

Thanks to Rob and Thierry G.

extension String {
    
    var nsRange: NSRange {
        return Foundation.NSRange(startIndex ..< endIndex, in: self)
    }
    
    subscript(nsRange: NSRange) -> Substring? {
        return Range(nsRange, in: self)
            .flatMap { self[$0] }
    }
    
    func substringAfterLastOccurenceOf(_ char: Character) -> String {
        
        let regex = try! NSRegularExpression(pattern: "\(char)\\s*(\\S[^\(char)]*)$")
        if let match = regex.firstMatch(in: self, range: self.nsRange), let result = self[match.range(at: 1)] {
            return String(result)
        }
        return ""
    }
}

we can use like this

let subStringAfterLastComma = "Hamilton, A".substringAfterLastOccurenceOf(",")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.