44

Given the following string:

var snippet = "1111 West Main Street Beverly Hills, CA 90210 Phone: 123.456.7891"

How can I extract everything that comes after "Phone:"

So in this case I want

phone = 123.456.7891

I've tried this:

    if let range = snippet.rangeOfString("Phone:") {

        let phone = snippet.substringToIndex(range.startIndex)
        print(phone) // prints 1111 West Main Street Beverly Hills, CA 90210
    }

But this prints everything BEFORE, I need everything AFTER.

user1625155
  • 501
  • 1
  • 8
  • 15

4 Answers4

90

In Swift 4, use upperBound and subscript operators and open range:

let snippet = "1111 West Main Street Beverly Hills, CA 90210 Phone: 123.456.7891"

if let range = snippet.range(of: "Phone: ") {
    let phone = snippet[range.upperBound...]
    print(phone) // prints "123.456.7891"
}

Or consider trimming the whitespace:

if let range = snippet.range(of: "Phone:") {
    let phone = snippet[range.upperBound...].trimmingCharacters(in: .whitespaces)
    print(phone) // prints "123.456.7891"
}

By the way, if you're trying to grab both at the same time, a regular expression can do that. E.g., in iOS 16 and later:

let snippet = "1111 West Main Street Beverly Hills, CA 90210 Phone: 123.456.7891"
if let match = snippet.firstMatch(of: /^(.*?)\s*Phone:\s*(.*)$/.ignoresCase()) {
    let address = match.output.1
    let phone = match.output.2
}

Or in earlier iOS versions, we might use NSRegularExpression:

let snippet = "1111 West Main Street Beverly Hills, CA 90210 Phone: 123.456.7891"
let regex = try! NSRegularExpression(pattern: #"^(.*?)\s*Phone:\s*(.*)$"#, options: .caseInsensitive)
if let match = regex.firstMatch(in: snippet, range: NSRange(snippet.startIndex..., in: snippet)) {
    let address = snippet[Range(match.range(at: 1), in: snippet)!]
    let phone = snippet[Range(match.range(at: 2), in: snippet)!]
}

For prior versions of Swift, see previous revision of this answer.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • first code snippet returns us `String.SubSequence`. To get `String`, we should use second code snippet which trims the white space and returns `String`, right? – Awais Fayyaz Aug 02 '18 at 07:44
  • Sorry for not responding to the comment earlier: Yep, if you are passing this result to a method or property that is expecting a `String`, then you can create a string from a substring (e.g. `let string = String(address)`), which involves copying the contents of a substring into another `String`. Alternatively, sometimes you can define your method to accept both strings and substrings by using `StringProtocol` rather than `String`. The question comes down to whether you need a separate `String` (and the overhead that entails) or whether you want to enjoy the efficiency of substrings. – Rob Feb 08 '23 at 18:39
20

for a very basic way and assuming you can guarantee the format of the string you could use .components(separatedBy: "Phone: ") so anything before will be at index 0 and after index 1

var snippet = "1111 West Main Street Beverly Hills, CA 90210 Phone: 123.456.7891"
let phoneNumber = snippet.components(separatedBy: "Phone: ")[1]
print(phoneNumber)
//prints everything that appears after "Phone: " in your snippet string
//"123.456.7891"
RyanTCB
  • 7,400
  • 5
  • 42
  • 62
  • This code not conforms to the requirements in the question. It will fail with several "Phone:" occurrences in the input. – std.denis Jul 19 '19 at 15:17
  • 1
    The Question did not state multiple occurrences of "Phone:". So your issue may not actually exist. To quote my own answer though "assuming you can guarantee the format of the string" – RyanTCB Jul 31 '20 at 10:10
4

Check it this

let delimiter = ", "
let newstr = "Hello, playground"
let token = newstr.components(separatedBy: delimiter)
let first = token[0]
let last = token[1]
print("\(first) \(last)")
Sreekanth G
  • 658
  • 6
  • 13
-2

Just use func substringFromIndex but increase the index by the length of "Phone:"

aahrens
  • 5,522
  • 7
  • 39
  • 63