Swift: разбить строку на массив

скажем, у меня есть строка здесь:

var fullName: String = "First Last"

Я хочу разделить базу строк на пробелы и присвоить значения их соответствующим переменным

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

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

кроме того, иногда у пользователей может не быть фамилии.

30 ответов


быстрый способ-использовать глобальный == " "} var firstName: String = fullNameArr[0] var lastName: String? = fullNameArr.count > 1 ? fullNameArr[1] : nil

С Swift 2

в Swift 2 Использование split становится немного сложнее из-за введения внутреннего типа CharacterView. Это означает, что String больше не принимает протоколы SequenceType или CollectionType и вместо этого необходимо использовать .characters свойство для доступа к представлению типа CharacterView экземпляра строки. (Примечание: CharacterView принимает Протоколы SequenceType и CollectionType).

let fullName = "First Last"
let fullNameArr = fullName.characters.split{ == " "}.map(String.init)
// or simply:
// let fullNameArr = fullName.characters.split{" "}.map(String.init)

fullNameArr[0] // First
fullNameArr[1] // Last 

просто позвони componentsSeparatedByString метод fullName

import Foundation

var fullName: String = "First Last"
let fullNameArr = fullName.componentsSeparatedByString(" ")

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

обновление для Swift 3+

import Foundation

let fullName    = "First Last"
let fullNameArr = fullName.components(separatedBy: " ")

let name    = fullNameArr[0]
let surname = fullNameArr[1]

самый простой способ сделать это с помощью componentsSeparatedBy:

Для Swift 2:

import Foundation
let fullName : String = "First Last";
let fullNameArr : [String] = fullName.componentsSeparatedByString(" ")

// And then to access the individual words:

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

Для Swift 3:

import Foundation

let fullName : String = "First Last"
let fullNameArr : [String] = fullName.components(separatedBy: " ")

// And then to access the individual words:

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

Swift Dev. 4.0 (24 мая 2017)

новая функция split в Swift 4 (бета).

import Foundation
let sayHello = "Hello Swift 4 2017";
let result = sayHello.split(separator: " ")
print(result)

выход:

["Hello", "Swift", "4", "2017"]

доступ к значениям:

print(result[0]) // Hello
print(result[1]) // Swift
print(result[2]) // 4
print(result[3]) // 2017

Xcode 8.1 / Swift 3.0.1

вот как несколько разделителей с массивом.

import Foundation
let mathString: String = "12-37*2/5"
let numbers = mathString.components(separatedBy: ["-", "*", "/"])
print(numbers)

выход:

["12", "37", "2", "5"]

в качестве альтернативы ответу WMios вы также можете использовать componentsSeparatedByCharactersInSet, что может быть удобно в случае, если у вас больше разделителей (пробел, запятая и т. д.).

С вашим конкретным входом:

let separators = NSCharacterSet(charactersInString: " ")
var fullName: String = "First Last";
var words = fullName.componentsSeparatedByCharactersInSet(separators)

// words contains ["First", "Last"]

использование нескольких сепараторов:

let separators = NSCharacterSet(charactersInString: " ,")
var fullName: String = "Last, First Middle";
var words = fullName.componentsSeparatedByCharactersInSet(separators)

// words contains ["Last", "First", "Middle"]

Swift 4

let words = "these words will be elements in an array".components(separatedBy: " ")

Xcode 9 Swift 4 или Xcode 8.2.1 * Swift 3.0.2

Если вам просто нужно правильно отформатировать имя человека, вы можете использовать PersonNameComponentsFormatter.

класс PersonNameComponentsFormatter предоставляет локализованные представления компонентов имени человека, как представлено объектом PersonNameComponents. Используйте этот класс для создания локализованного имена при отображении информации об имени лица пользователь.


// iOS (9.0 and later), macOS (10.11 and later), tvOS (9.0 and later), watchOS (2.0 and later)
let nameFormatter = PersonNameComponentsFormatter()

let name =  "Mr. Steven Paul Jobs Jr."
// personNameComponents requires iOS (10.0 and later)
if let nameComps  = nameFormatter.personNameComponents(from: name) {
    nameComps.namePrefix   // Mr.
    nameComps.givenName    // Steven
    nameComps.middleName   // Paul
    nameComps.familyName   // Jobs
    nameComps.nameSuffix   // Jr.

    // It can also be convufgured to format your names
    // Default (same as medium), short, long or abbreviated

    nameFormatter.style = .default
    nameFormatter.string(from: nameComps)   // "Steven Jobs"

    nameFormatter.style = .short
    nameFormatter.string(from: nameComps)   // "Steven"

    nameFormatter.style = .long
    nameFormatter.string(from: nameComps)   // "Mr. Steven Paul Jobs jr."

    nameFormatter.style = .abbreviated
    nameFormatter.string(from: nameComps)   // SJ

    // It can also be use to return an attributed string using annotatedString method
    nameFormatter.style = .long
    nameFormatter.annotatedString(from: nameComps)   // "Mr. Steven Paul Jobs jr."
}

enter image description here


проблема пробелов

как правило, люди придумывают эту проблему и плохие решения снова и снова. Это пространство? ""а как насчет "\n", "\t " или какого-то символа Юникода, который вы никогда не видели, в немалой степени потому, что он невидим. В то время как вы можете уйти с

слабое решение

import Foundation
let pieces = "Mary had little lamb".componentsSeparatedByString(" ")

Если вам когда-нибудь нужно встряхнуть вашу хватку на реальность смотреть видео WWDC на строки или даты. Короче говоря, почти всегда лучше разрешить Apple решить такую мирскую задачу.

Надежное Решение: Используйте NSCharacterSet

способ сделать это правильно, ИМХО, использовать NSCharacterSet поскольку, как указано ранее, ваши пробелы могут быть не такими, как вы ожидаете, и Apple предоставила набор символов пробелов. Чтобы изучить различные предоставленные наборы символов, ознакомьтесь сдокументация для разработчиков NSCharacterSet и тогда, только тогда, увеличить или создайте новый набор символов, если он не соответствует вашим потребностям.

пробелы NSCharacterSet

возвращает набор символов, содержащий символы в Unicode General Категория Zs и табуляция символов (U + 0009).

let longerString: String = "This is a test of the character set splitting system"
let components = longerString.components(separatedBy: .whitespaces)
print(components)

Swift 4 упрощает разделение символов, просто используйте новую функцию разделения для строк.

пример: let s = "hi, hello" let a = s.split(separator: ",") print(a)

теперь у вас есть массив с "привет" и "привет".


Swift 3

let line = "AAA    BBB\t CCC"
let fields = line.components(separatedBy: .whitespaces).filter {!.isEmpty}
  • возвращает три строки AAA, BBB и CCC
  • отфильтровывает пустые поля
  • обрабатывает несколько пробелов и символов табуляции
  • если вы хотите обрабатывать новые строки, замените .whitespaces С .whitespacesAndNewlines

Xcode 8.0 / Swift 3

let fullName = "First Last"
var fullNameArr = fullName.components(separatedBy: " ")

var firstname = fullNameArr[0] // First
var lastname = fullNameArr[1] // Last

Долгий Путь:

var fullName: String = "First Last"
fullName += " " // this will help to see the last word

var newElement = "" //Empty String
var fullNameArr = [String]() //Empty Array

for Character in fullName.characters {
    if Character == " " {
        fullNameArr.append(newElement)
        newElement = ""
    } else {
        newElement += "\(Character)"
    }
}


var firsName = fullNameArr[0] // First
var lastName = fullNameArr[1] // Last

Я нашел интересный случай, что

Способ 1

var data:[String] = split( featureData ) {  == "\u{003B}" }

когда я использовал эту команду для разделения некоторого символа из данных, загруженных с сервера, он может разделяться во время тестирования в симуляторе и синхронизации с тестовым устройством, но он не будет разделяться в приложении публикации и Ad Hoc

мне нужно много времени, чтобы отследить эту ошибку, она может быть проклята из какой-то версии Swift, или какой-то версии iOS или ни

дело не в HTML-код также, так как я пытаюсь stringByRemovingPercentEncoding и это все еще не работает

дополнительно 10/10/2015

в Swift 2.0 этот метод был изменен на

var data:[String] = featureData.split { == "\u{003B}"}

Способ 2

var data:[String] = featureData.componentsSeparatedByString("\u{003B}")

когда я использовал эту команду, он может разделить те же данные, которые загружаются с сервера правильно


вывод, я действительно предлагаю использовать метод 2

string.componentsSeparatedByString("")

У меня был сценарий, где несколько управляющих символов могут присутствовать в строке, которую я хочу разделить. Вместо того, чтобы поддерживать массив из них, я просто позволяю Apple обрабатывать эту часть.

следующие работы с Swift 3.0.1 на iOS 10:

let myArray = myString.components(separatedBy: .controlCharacters)

большинство из этих ответов предполагают, что вход содержит пробел-не белыйпространство, и одно пространство при этом. Если вы можете с уверенностью сделать это предположение, то принятый ответ (от Беннетта) довольно элегантен, а также метод, с которым я буду идти, когда смогу.

когда мы не можем сделать это предположение, более надежное решение должно охватывать следующие сьютации, которые большинство ответов здесь не учитывают:

  • вкладки / новые строки / пробелы (пробелы), в том числе повторяющиеся символы
  • начальные/конечные пробельные символы
  • Apple / Linux (\n) и Windows (\r\n) символы новой строки

для покрытия этих случаев это решение использует регулярное выражение для преобразования всех пробелов (включая повторяющиеся и символы новой строки Windows) в одно пространство, обрезки, а затем разбивается на одно пространство:

Swift 3:

let searchInput = "  First \r\n \n \t\t\tMiddle    Last "
let searchTerms = searchInput 
    .replacingOccurrences(
        of: "\s+",
        with: " ",
        options: .regularExpression
    )
    .trimmingCharacters(in: .whitespaces)
    .components(separatedBy: " ")

// searchTerms == ["First", "Middle", "Last"]

или без замыканий вы можете сделать это только в Swift 2:

let fullName = "First Last"
let fullNameArr = fullName.characters.split(" ")
let firstName = String(fullNameArr[0])

Swift 4, Xcode 10 и iOS 12 обновление 100% работает

let fullName = "First Last"    
let fullNameArr = fullName.components(separatedBy: " ")
let firstName = fullNameArr[0] //First
let lastName = fullnameArr[1] //Last

посмотреть документация Apple здесь для получения дополнительной информации.


надеюсь, что это полезно

Swift 4: разбить строку на массив. Шаг 1: назначьте строку. Шаг 2: на основе @ spliting. Примечание: имя_переменной.компоненты (separatedBy: "ключевое слово split")

let fullName: String = "First Last @ triggerd event of the session by session storage @ it can be divided by the event of the trigger."
let fullNameArr = fullName.components(separatedBy: "@")
print("split", fullNameArr)

в Swift 4.1 и Xcode 9.4.1

//This is your str
let str = "This is my String" //Here replace with your string

1

let items = str.components(separatedBy: " ")//Here replase space with your value and result is Array.
//Direct line of code
//let items = "This is my String".components(separatedBy: " ")
let str1 = items[0]
let str2 = items[1]
let str3 = items[2]
let str4 = items[3]
//OutPut
print(items.count)
print(str1)
print(str2)
print(str3)
print(str4)
print(items.first!)
print(items.last!)

2

let items = str.split(separator: " ")
let str1 = String(items.first!)
let str2 = String(items.last!)
//Output
print(items.count)
print(items)
print(str1)
print(str2)

3

let arr = str.split { == " "}
print(arr)

4

По Документации Apple....

let line = "BLANCHE:   I don't want realism. I want magic!"
print(line.split(separator: " "))
print(line.split(separator: " ", maxSplits: 1))//This can split your string into 2 parts
print(line.split(separator: " ", maxSplits: 2))//This can split your string into 3 parts
print(line.split(separator: " ", omittingEmptySubsequences: false))//array contains empty strings where spaces were repeated.
print(line.split(separator: " ", omittingEmptySubsequences: true))//array not contains empty strings where spaces were repeated.
print(line.split(separator: " ", maxSplits: 4, omittingEmptySubsequences: false))
print(line.split(separator: " ", maxSplits: 3, omittingEmptySubsequences: true))

let str = "one two"
let strSplit = str.characters.split(" ").map(String.init) // returns ["one", "two"]

Xcode 7.2 (7C68)


Swift 2.2 добавлена обработка ошибок и capitalizedString:

func setFullName(fullName: String) {
    var fullNameComponents = fullName.componentsSeparatedByString(" ")

    self.fname = fullNameComponents.count > 0 ? fullNameComponents[0]: ""
    self.sname = fullNameComponents.count > 1 ? fullNameComponents[1]: ""

    self.fname = self.fname!.capitalizedString
    self.sname = self.sname!.capitalizedString
}

предположим, у вас есть переменная с именем "Hello World", и если вы хотите разделить ее и сохранить в двух разных переменных, вы можете использовать следующее:

var fullText = "Hello World"
let firstWord = fullText.text?.components(separatedBy: " ").first
let lastWord = fullText.text?.components(separatedBy: " ").last

это снова изменилось в бета-версии 5. Оээо! Теперь это метод CollectionType

старый:

var fullName = "First Last"
var fullNameArr = split(fullName) { == " "}

New:

var fullName = "First Last"
var fullNameArr = fullName.split { == " "}

Яблоки Примечания К Выпуску


для swift 2, XCode 7.1:

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

согласно Swift 2.2

вы просто пишете код строки 2, и вы получите разделенную строку.

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

наслаждайтесь. :)


вот алгоритм, который я только что построил, который разделит String любым Character из массива, и если есть желание сохранить подстроки с разделенными символами, можно установить до 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 .characters.contains(splitCharacter) {

                        return false
                    }
                }
                return true
            }
        }
    }
}

пример:

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

обработка строк по-прежнему является проблемой в Swift, и она продолжает значительно меняться, как вы можете видеть из других ответов. Надеюсь, все уляжется и станет проще. Это способ сделать это с текущей версией Swift 3.0 с несколькими символами разделителя.

Swift 3:

let chars = CharacterSet(charactersIn: ".,; -")
let split = phrase.components(separatedBy: chars)

// Or if the enums do what you want, these are preferred. 
let chars2 = CharacterSet.alphaNumerics // .whitespaces, .punctuation, .capitalizedLetters etc
let split2 = phrase.components(separatedBy: chars2)

Swift 4

let string = "loremipsum.dolorsant.amet:"

let result = string.components(separatedBy: ".")

print(result[0])
print(result[1])
print(result[2])
print("total: \(result.count)")

выход

loremipsum
dolorsant
amet:
total: 3

искал loosy split, например, PHP explode где пустые последовательности включены в результирующий массив, это сработало для меня:

"First ".split(separator: " ", maxSplits: 1, omittingEmptySubsequences: false)

выход:

["First", ""]

Я не нашел решение, которое будет обрабатывать имена с 3 или более компонентами и поддерживать более старые версии iOS.

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)
    }
}

прошел тест-кейсы:

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)
}

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"
  • запретить одно и то же имя и фамилию
  • Если полное имя недопустимо, возьмите значение-заполнитель "John Doe"