843

Say I have a string here:

var fullName: String = "First Last"

I want to split the string based on whitespace and assign the values to their respective variables

var fullNameArr = // something like: fullName.explode(" ") 

var firstName: String = fullNameArr[0]
var lastName: String? = fullnameArr[1]

Also, sometimes users might not have a last name.

4
  • 17
    Hi, i dont have my Mac to check. But you can try 'fullName.componentsSeparatedByString(string:" ")' Dont copy and paste, use the autocompletefunction, so you get the right function. Commented Sep 5, 2014 at 4:08
  • If you are only splitting by one character, using fullName.utf8.split( <utf-8 character code> ) works as well (replace .utf8 with .utf16 for UTF-16). For example, splitting on + could be done using fullName.utf8.split(43) Commented Dec 25, 2015 at 7:41
  • Also, sometimes last names have spaces in them, as in "Daphne du Maurier" or "Charles de Lint" Commented Jul 27, 2017 at 16:45
  • I found this nice: Split a string by single delimiter, String splitting by multiple delimiters, String splitting by word delimiter Commented Jan 31, 2020 at 11:31

41 Answers 41

1
2
2

Do not use whitespace to separate words. It will not work well for English. And it will not work at all for languages like Japanese or Chinese.

Here is a sample for tokenizing names from a given string:

import NaturalLanguage

actor Tokenizer {
    private let tagger = NLTagger(tagSchemes: [.nameType])

    func tokens(for text: String) async -> [String] {
        tagger.string = text

        let tags = tagger.tags(
            in: text.startIndex ..< text.endIndex,
            unit: .word,
            scheme: .nameType,
            options: [
                .omitPunctuation,
                .omitWhitespace,
                .joinNames,
            ]
        )

        return tags.map { String(text[$1]) }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Is the NLTagger .nameType smart enough to handle cases like "van Der Wal" or "de Gaulle" where the name contains spaces?
1

For swift 2, XCode 7.1:

let complete_string:String = "Hello world"
let string_arr =  complete_string.characters.split {$0 == " "}.map(String.init)
let hello:String = string_arr[0]
let world:String = string_arr[1]

Comments

1

Here is an algorithm I just build, which will split a String by any Character from the array and if there is any desire to keep the substrings with splitted characters one could set the swallow parameter to true.

Xcode 7.3 - Swift 2.2:

extension String {

    func splitBy(characters: [Character], swallow: Bool = false) -> [String] {

        var substring = ""
        var array = [String]()
        var index = 0

        for character in self.characters {

            if let lastCharacter = substring.characters.last {

                // swallow same characters
                if lastCharacter == character {

                    substring.append(character)

                } else {

                    var shouldSplit = false

                    // check if we need to split already
                    for splitCharacter in characters {
                        // slit if the last character is from split characters or the current one
                        if character == splitCharacter || lastCharacter == splitCharacter {

                            shouldSplit = true
                            break
                        }
                    }

                    if shouldSplit {

                        array.append(substring)
                        substring = String(character)

                    } else /* swallow characters that do not equal any of the split characters */ {

                        substring.append(character)
                    }
                }
            } else /* should be the first iteration */ {

                substring.append(character)
            }

            index += 1

            // add last substring to the array
            if index == self.characters.count {

                array.append(substring)
            }
        }

        return array.filter {

            if swallow {

                return true

            } else {

                for splitCharacter in characters {

                    if $0.characters.contains(splitCharacter) {

                        return false
                    }
                }
                return true
            }
        }
    }
}

Example:

"test text".splitBy([" "]) // ["test", "text"]
"test++text--".splitBy(["+", "-"], swallow: true) // ["test", "++" "text", "--"]

Comments

1

Simple way to split a string into array

var fullName: String = "First Last";

var fullNameArr = fullName.componentsSeparatedByString(" ")

var firstName: String = fullNameArr[0]
var lastName: String = fullNameArr[1]

1 Comment

Already mentioned in several answers.
0

As per Swift 2.2

You just write 2 line code and you will get the split string.

let fullName = "FirstName LastName"
var splitedFullName = fullName.componentsSeparatedByString(" ")
print(splitedFullName[0])
print(splitedFullName[1]) 

Enjoy. :)

1 Comment

Same answer as stackoverflow.com/a/25678505/2227743 on this page. Please read the other answers before posting yours. Thank you.
0

I haven't found the solution that would handle names with 3 or more components and support older iOS versions.

struct NameComponentsSplitter {

    static func split(fullName: String) -> (String?, String?) {
        guard !fullName.isEmpty else {
            return (nil, nil)
        }
        let components = fullName.components(separatedBy: .whitespacesAndNewlines)
        let lastName = components.last
        let firstName = components.dropLast().joined(separator: " ")
        return (firstName.isEmpty ? nil : firstName, lastName)
    }
}

Passed test cases:

func testThatItHandlesTwoComponents() {
    let (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Smith")
    XCTAssertEqual(firstName, "John")
    XCTAssertEqual(lastName, "Smith")
}

func testThatItHandlesMoreThanTwoComponents() {
    var (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Clark Smith")
    XCTAssertEqual(firstName, "John Clark")
    XCTAssertEqual(lastName, "Smith")

    (firstName, lastName) = NameComponentsSplitter.split(fullName: "John Clark Jr. Smith")
    XCTAssertEqual(firstName, "John Clark Jr.")
    XCTAssertEqual(lastName, "Smith")
}

func testThatItHandlesEmptyInput() {
    let (firstName, lastName) = NameComponentsSplitter.split(fullName: "")
    XCTAssertEqual(firstName, nil)
    XCTAssertEqual(lastName, nil)
}

Comments

0
let fullName : String = "Steve.Jobs"
let fullNameArr : [String] = fullName.components(separatedBy: ".")

var firstName : String = fullNameArr[0]
var lastName : String = fullNameArr[1]

4 Comments

Some explanation about why this produces the desired results would be helpful.
Please give some explanation, it's always better to do so.
From review queue: May I request you to please add some more context around your answer. Code-only answers are difficult to understand. It will help the asker and future readers both if you can add more information in your post. See also Explaining entirely code-based answers.
here fullName is a string separated by a "." using fullName.components(separatedBy: ".") default apple provided function and it returns an array of string
0
var fullName = "James Keagan Michael"
let first = fullName.components(separatedBy: " ").first?.isEmpty == false ? fullName.components(separatedBy: " ").first! : "John"
let last =  fullName.components(separatedBy: " ").last?.isEmpty == false && fullName.components(separatedBy: " ").last != fullName.components(separatedBy: " ").first ? fullName.components(separatedBy: " ").last! : "Doe"
  • Disallow same first and last name
  • If a fullname is invalid, take placeholder value "John Doe"

Comments

0

Expounding off of Don Vaughn's Answer, I liked the use of Regular Expressions. I'm surprised that this is only the 2nd Regex answer. However, if we could solve this in just one split method, instead of multiple methods, that would be great.

I was also inspired by Mithra Singam's Answer to exclude all punctuation as well as whitespace. However, having to create a list of disallowed characters didn't vibe with me.

  • \w - Regular Expression for a Letter or Number symbol. No punctuation.
let foo = "(..#   Hello,,(---- World   ".split {
    String($0).range(of: #"\w"#, options: .regularExpression) == nil
}
print(foo) // Prints "Hello World"

Let's say you aren't comfortable will all of Unicode. How about just ASKII Letters and Numbers?

let bar = "(..#   Hello,,(---- World   ".split {
    !($0.isASCII && ($0.isLetter || $0.isNumber))
}
print(bar) // Prints "Hello World"

Comments

-2

You can use this common function and add any string which you want to separate

func separateByString(String wholeString: String, byChar char:String) -> [String] {

    let resultArray = wholeString.components(separatedBy: char)
    return resultArray
}

var fullName: String = "First Last"
let array = separateByString(String: fullName, byChar: " ")
var firstName: String = array[0]
var lastName: String = array[1]
print(firstName)
print(lastName)

1 Comment

Hi. In Swift, parameters name should always start with lowercase. Like: separateByString(string wholeString: String, byChar char:String). Also this way avoids conflating the variable name with a type.
-2

This is for String and CSV file for swift 4.2 at 20181206 1610

var dataArray : [[String]] = []
 let path = Bundle.main.path(forResource: "csvfilename", ofType: "csv")
        let url = URL(fileURLWithPath: path!)
        do {
            let data = try Data(contentsOf: url) 
            let content = String(data: data, encoding: .utf8)
            let parsedCSV = content?.components(separatedBy: "\r\n").map{ $0.components(separatedBy: ";") }
           for line in parsedCSV!
            {
                dataArray.append(line)
           }
        }
        catch let jsonErr {
            print("\n   Error read CSV file: \n ", jsonErr)
        }

            print("\n MohNada 20181206 1610 - The final result is \(dataArray)  \n ")

Comments

1
2

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.