Разбить строку в массив в Swift?

551

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

var fullName: String = "First Last"

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

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

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

Кроме того, иногда пользователи могут не иметь фамилии.

  • 11
    Привет, у меня нет моего Mac, чтобы проверить. Но вы можете попробовать 'fullName.componentsSeparatedByString (string: "")' Не копировать и вставлять, используйте функцию автозаполнения, чтобы получить правильную функцию.
  • 0
    Если вы .utf8 только на один символ, то также работает fullName.utf8.split( <utf-8 character code> ) (замените .utf8 на .utf16 для UTF-16). Например, разделение на + может быть сделано с использованием fullName.utf8.split(43)
Показать ещё 2 комментария
Теги:
string
split

32 ответа

754
Лучший ответ

Способ Swift - использовать глобальную функцию split, например:

var fullName = "First Last"
var fullNameArr = split(fullName) {$0 == " "}
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 экземпляра String. (Примечание: CharacterView использует протоколы SequenceType и CollectionType).

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

fullNameArr[0] // First
fullNameArr[1] // Last 
  • 87
    В моих тестах componentSeparatedByString обычно значительно быстрее, особенно при работе со строками, которые требуют разбиения на множество частей. Но для примера, указанного в OP, должно хватить любого.
  • 9
    Начиная с Xcode 6.2b3 split может использоваться как split("a:b::c:", {$0 == ":"}, maxSplit: Int.max, allowEmptySlices: false) .
Показать ещё 20 комментариев
878

Просто наберите 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]
  • 56
    Этот ответ гораздо элегантнее принятого. Программисты из Тайваня потрясающие: D
  • 3
    Обратите внимание, что это на самом деле базовая NSString (Swift автоматически меняет их при импорте Foundation ).
Показать ещё 14 комментариев
152

Самый простой способ сделать это - использовать компонентыSeparatedBy:

Для 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]
  • 0
    Это где-нибудь задокументировано, Мори? Что если мне нужно разделить что-то, кроме одного символа?
  • 9
    @NRitH рассмотреть .componentsSeparatedByCharactersInSet(.whitespaceAndNewlineCharacterSet())
Показать ещё 3 комментария
96

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"]
  • 8
    Убедитесь, что вы добавили import Foundation в класс, в котором вы это используете. #SavedYouFiveMinutes
  • 4
    Внимание (Swift 4): если у вас есть строка типа let a="a,,b,c" и вы используете a.split(separator: ",") вы получите массив типа ["a", "b", c"] по умолчанию. Это можно изменить с помощью omittingEmptySubsequences: false который по умолчанию имеет значение true.
Показать ещё 1 комментарий
50

В качестве альтернативы ответу 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"]
  • 2
    Самый полезный ответ на мой взгляд, так как вы можете захотеть , чтобы обеспечить разделение строк с , или ; или любой другой разделитель
  • 1
    Это намного проще, чем принятый ответ!
Показать ещё 2 комментария
46

Swift 4

let words = "these words will be elements in an array".components(separatedBy: " ")
  • 0
    Xcode 9.2 нет метода components на строках
  • 1
    @ да, да, есть. Ответ Бобби действителен.
Показать ещё 2 комментария
38

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 configured 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."
}

Изображение 1581

  • 1
    Это действительно хороший API, предоставленный Apple и хорошо объясненный. + 1
25

Пробел

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

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

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

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

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

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

Пробелы NSCharacterSet

Возвращает набор символов, содержащий символы в Unicode General Category Zs и CHARACTER TABULATION (U + 0009).

let longerString: String = "This is a test of the character set splitting system"
let components = longerString.components(separatedBy: .whitespaces)
print(components)
  • 1
    Согласовано. Первое, что пришло мне в голову после просмотра ответов, разделенных на «», это: что произойдет, если входной текст содержит несколько последовательных пробелов? Что делать, если у него есть вкладки? Полноразмерное (CJK) пространство? и т.п.
  • 1
    Определенно лучший ответ здесь.
19

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

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

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

  • 2
    Спасибо за этот ответ, так полезно. Мне нравится, как Swift 4 делает синтаксис коротким и простым.
  • 0
    Обратите внимание, что это не возвращает массив String, но массив Substring, который неудобно использовать.
14

Swift 3

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

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
11

В Swift 4.2 и Xcode 10

//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 {$0 == " "}
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))
8

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.

8

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

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

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

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

метод 1

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

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

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

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

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

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

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

метод 2

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

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


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

string.componentsSeparatedByString("")
  • 1
    Я бы сказал, что это близко к статусу «не ответ», так как в основном это комментарии к существующим ответам. Но это указывает на что-то важное.
7

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

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

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

Чтобы охватить эти случаи, это решение использует regex для преобразования всех пробелов (включая повторяющиеся символы и символы новой строки 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"]
6

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

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

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

Swift 4: разделите строку на массив. Шаг 1: назначьте строку. Шаг 2: основан на @spliting. Примечание: variableName.components (разделенныеBy: "split keyword")

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

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

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

Swift 2.2 Обработка ошибок и capizedizedString Добавлено:

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
}
2
let str = "one two"
let strSplit = str.characters.split(" ").map(String.init) // returns ["one", "two"]

Xcode 7.2 (7C68)

1

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

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

Выход:

["First", ""]
1

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
1

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

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

Вот алгоритм, который я только что создаю, который разбивает String на любой Character из массива, и если есть желание сохранить подстроки с разделенными символами, можно установить параметр swallow в 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
            }
        }
    }
}

Пример:

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

Согласно Swift 2.2

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

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

Enjoy.:)

  • 1
    Тот же ответ, что и stackoverflow.com/a/25678505/2227743 на этой странице. Пожалуйста, прочитайте другие ответы, прежде чем публиковать свои . Спасибо.
1

Для быстрого 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]
  • 0
    По какой-то конкретной причине это было понижено? Кажется, работает для меня, а также в Xcode 7.1.
1

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

Старый:

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

Новое:

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

Заметки о выпуске яблок

0

Это для String и CSV файла для swift 4.2 на странице 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 ")
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"
  • Отменить одно и то же имя и фамилию
  • Если полное имя недействительно, введите значение "John Doe",
0

Я не нашел решение, которое обрабатывало бы имена с 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)
}
-2

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

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)
  • 0
    Привет. В Swift имя параметра всегда должно начинаться со строчной буквы. Например: separateByString(string wholeString: String, byChar char:String) . Также этот способ позволяет избежать путаницы имени переменной с типом.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню