Swift : How to get the string before a certain character?

IosSwift

Ios Problem Overview


How do I get the string before a certain character in swift? The code below is how I did it in Objective C, but can't seem to perform the same task in Swift. Any tips or suggestions on how to achieve this? rangeOfString seems to not work at all in swift (although Swift has been acting up for me again).

NSRange range = [time rangeOfString:@" "];
NSString *startDate =
[time substringToIndex:range.location];

As you can see from the code above I am able to get the string before the space character in Objective C.

Edit : If I try something like this

 var string = "hello Swift"
 var range : NSRange = string.rangeOfString("Swift")

I get the following error.

> Cannot convert the expression's type 'NSString' to type '(String, > options: NSStringCompareOptions, range: Range?, locale: > NSLocale?)'

Not sure what I did wrong exactly or how to resolve it correctly.

Ios Solutions


Solution 1 - Ios

Use componentsSeparatedByString() as shown below:

var delimiter = " "
var newstr = "token0 token1 token2 token3"
var token = newstr.components(separatedBy: delimiter)
print (token[0])

Or to use your specific case:

var delimiter = " token1"
var newstr = "token0 token1 token2 token3"
var token = newstr.components(separatedBy: delimiter)
print (token[0])

Solution 2 - Ios

You can do the same with rangeOfString() provided by String class

let string = "Hello Swift"
if let range = string.rangeOfString("Swift") {
   let firstPart = string[string.startIndex..<range.startIndex]
   print(firstPart) // print Hello
}

You can also achieve it with your method substringToIndex()

let string = "Hello Swift"
if let range = string.rangeOfString("Swift") {
   firstPart = string.substringToIndex(range.startIndex)
   print(firstPart) // print Hello
}

Swift 3 UPDATE:

let string = "Hello Swift"
if let range = string.range(of: "Swift") {
    let firstPart = string[string.startIndex..<range.lowerBound]
    print(firstPart) // print Hello
}

Hope this can help you ;)

Solution 3 - Ios

Following up on Syed Tariq's answer: If you only want the string before the delimiter (otherwise, you receive an array [String]):

var token = newstr.components(separatedBy: delimiter).first

Solution 4 - Ios

You could use the method prefix(upTo:) in Swift 4 or above

var string = "hello Swift"
if let index = string.firstIndex(of: " ") {
    let firstPart = string.prefix(upTo: index)
    print(firstPart) // print hello
}

Solution 5 - Ios

Swift 5 extension

extension String {
    func before(first delimiter: Character) -> String {
        if let index = firstIndex(of: delimiter) {
            let before = prefix(upTo: index)
            return String(before)
        }
        return ""
    }
    
    func after(first delimiter: Character) -> String {
        if let index = firstIndex(of: delimiter) {
            let after = suffix(from: index).dropFirst()
            return String(after)
        }
        return ""
    }
}

let str = "n1:lolz"
str.before(first: ":") // n1
str.after(first: ":") // lolz
str.after(first: "z") // empty string
str.before(first: "n") // empty string
str.before(first: "g") // empty string

I think it makes as much sense to return an optional String for preference (returning nil if there isn't anything before or after the delimiter).

Solution 6 - Ios

My 2 cents :-) using Swift 3.0, similar to PHP strstr

extension String {

    func strstr(needle: String, beforeNeedle: Bool = false) -> String? {
        guard let range = self.range(of: needle) else { return nil }

        if beforeNeedle {
            return self.substring(to: range.lowerBound)
        }

        return self.substring(from: range.upperBound)
    }

}

Usage1

"Hello, World!".strstr(needle: ",", beforeNeedle: true) // returns Hello

Usage2

"Hello, World!".strstr(needle: " ") // returns World!

Solution 7 - Ios

To mutate a String into the part until the first appearance of a specified String you could extend String like this:

extension String {

    mutating func until(_ string: String) {
        let components = self.components(separatedBy: string)
        self = components[0]
    }

}

This can be called like this then:

var foo = "Hello Swift"
foo.until(" Swift") // foo is now "Hello"

Solution 8 - Ios

If you want a solution that doesn't involve pulling in foundation, you can do it with find and slicing:

let str = "Hello, I must be going."

if let comma = find(str, ",") {
    let substr = str[str.startIndex..<comma]
    // substr will be "Hello"
}

If you explicitly want an empty string in the case where no such character is found, you can use the nil-coalescing operator:

let str = "no comma"
let comma = find(str, ",") ?? str.startIndex
let substr = str[str.startIndex..<comma]  // substr will be ""

Note, unlike the componentsSeparatedByString technique, this does not require the creation of an array, and only requires scanning up to the first occurrence of the character rather than breaking the entire string up into the character-delimited array.

Solution 9 - Ios

You can use rangeOfString, but it returns a Range<String.Index> type, not a NSRange:

let string = "hello Swift"
if let range = string.rangeOfString("Swift") {
    print(string.substringToIndex(range.startIndex))
}

Solution 10 - Ios

let string = "Hello-world"
if let range = string.range(of: "-") {
let firstPart = string[(string.startIndex)..<range.lowerBound]
 print(firstPart) 
}

Output is: Hello

Solution 11 - Ios

Below is kind of a whole combo

let string = "This a string split using * and this is left."
if let range = string.range(of: "*") {
    let lastPartIncludingDelimiter = string.substring(from: range.lowerBound)
    print(lastPartIncludingDelimiter) // print * and this is left.
    
    let lastPartExcludingDelimiter = string.substring(from: range.upperBound)
    print(lastPartExcludingDelimiter) // print and this is left.
    
    let firstPartIncludingDelimiter = string.substring(to: range.upperBound)
    print(firstPartIncludingDelimiter) // print This a string split using *
    
    let firstPartExcludingDelimiter = string.substring(to: range.lowerBound)
    print(firstPartExcludingDelimiter) // print This a string split using
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDanger VegerView Question on Stackoverflow
Solution 1 - IosSyed TariqView Answer on Stackoverflow
Solution 2 - IosKevin MachadoView Answer on Stackoverflow
Solution 3 - IosTim NewtonView Answer on Stackoverflow
Solution 4 - IosMichael WangView Answer on Stackoverflow
Solution 5 - Iosfake girlfriendsView Answer on Stackoverflow
Solution 6 - IosAamirRView Answer on Stackoverflow
Solution 7 - IosBenno KressView Answer on Stackoverflow
Solution 8 - IosAirspeed VelocityView Answer on Stackoverflow
Solution 9 - IosRobView Answer on Stackoverflow
Solution 10 - IosSai kumar ReddyView Answer on Stackoverflow
Solution 11 - Iosanoop4realView Answer on Stackoverflow