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


687

Скажіть, у мене тут є рядок:

var fullName: String = "First Last"

Я хочу розділити базу рядків на пробіл і призначити значення їх відповідним змінним

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

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

Також іноді користувачі можуть не мати прізвища.


13
Привіт, я не маю Mac перевірити. Але ви можете спробувати 'fullName.componentsSeparatedByString (string: "") "Не копіюйте та вставляйте, використовуйте функцію автозаповнення, щоб ви отримали потрібну функцію.
Девід Гьолжаузер,

Якщо ви тільки розщеплення на один символ, з допомогою fullName.utf8.split( <utf-8 character code> )творів , а також (замінити .utf8з .utf16на UTF-16). Наприклад, розщеплення +можна зробити за допомогоюfullName.utf8.split(43)
Jojodmo

Також іноді в прізвищах є пробіли в них, як у "Дафні дю Маур'є" або "Шарль де Лінт"
Беррі

Відповіді:


784

Швидкий спосіб полягає у використанні глобальної 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 використання спліт стає дещо складнішим через впровадження внутрішнього типу 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 

98
У моїх тестах компонентиSeparatedByString, як правило, значно швидше, особливо при роботі з рядками, які вимагають розщеплення на багато фрагментів. Але для прикладу, перерахованого ОП, або має бути достатньо.
Кейсі Перкінс

9
Станом на Xcode 6.2b3 може використовуватися сплітsplit("a:b::c:", {$0 == ":"}, maxSplit: Int.max, allowEmptySlices: false) .
Паскаль

14
Просто пам’ятайте, що вам все-таки потрібно використовувати старий componentsSeparatedByString()метод, якщо ваш роздільник є чим-небудь довшим, ніж один символ. І як круто, як би сказати let (firstName, lastName) = split(fullName) {$0 == ' '}, це, на жаль, не працює.
NRitH

3
@Kashif тоді ви можете використовувати split("a,b;c,d") {$0 == "," || $0 == ";"}абоsplit("a,b;c,d") {contains(",;", $0)}
Етан

4
Правильний код для Xcode 7.0 нехай fullNameArr = fullName.characters.split {$ 0 == ""} .map (String.init). Спробував редагувати, але його відхилили.
skagedal

1015

Просто виклик 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]

3
Зауважте, що це насправді основне NSString(Swift автоматично підміняє їх під час імпорту Foundation).
Може

1
Що більше не стосується Swift 1.2, в якому Apple більше не перетворює String Swift в NSString автоматично.
elcuco

6
Ця відповідь працює у Xcode 7 beta 4 та Swift 2.0. Тепер Xcode автоматично завершує методи фундаменту на об'єктах Swift String без набору типів на NSString, що не стосується Xcode 6.4 із Swift 1.2.
Андрій

1
Це не працювало в системі REPL, поки я не імпортував Foundation.
Велізар Христов

1
Це працює точно так, як очікувалося (тобто fullNameArr є [String]) у Xcode 7.2.
Джон Кокс

185

Найпростіший метод зробити це за допомогою компонентів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]

Це десь задокументовано, Морі? Що робити, якщо мені потрібно розділитись на щось інше, ніж один персонаж?
NRitH

10
@NRitH вважайте .componentsSeparatedByCharactersInSet(.whitespaceAndNewlineCharacterSet())
rmp251

@Crashalot є дві функції: componentsSeparatedByStringіcomponentsSeparatedByCharactersInSet
rmp251

131

Швидкий Дев. 4,0 (24 травня 2017 р.)

Нова функція splitу Swift 4 ( Beta ).

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, яка за замовчуванням є.
OderWat

2
Будь-які розбиття на кілька символів у Swift 4+?
pamamb

57

Swift 4 або пізнішої версії

Якщо вам просто потрібно правильно відформатувати ім’я людини, ви можете використовувати 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."
}

введіть тут опис зображення

редагування / оновлення:

Swift 5 або пізнішої версії

Для простого розщеплення рядка за допомогою символів, які не бувають, ми можемо використовувати нову властивість символів isLetter:

let fullName = "First Last"

let components = fullName.split{ !$0.isLetter }
print(components)  // "["First", "Last"]\n"

1
@DarrellRoot вам просто потрібно скласти карту підрядківfullName.split { $0.isWhitespace }.map(String.init)
Лео Дабус

2
Я люблю цей новий API, але майте на увазі, що він повертає Підрядки. Мені були потрібні Strings (і хотілося розділити на пробіли взагалі), тому я це зробив: let words = line.split{ $0.isWhitespace }.map{ String($0)} Дякую @LeoDabus за вашу версію (у моєму первісному коментарі відсутній код). Також я пропоную перемістити версію Swift 5 до вершини відповіді.
Даррелл Корінь

53

В якості альтернативи відповіді 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
Найкорисніший відповідь на мій погляд, так як ви можете захотіти , щоб забезпечити поділ рядків з ,або ;будь-якої іншої роздільник
Кріс

49

Швидкий 4

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

34

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

Як правило, люди винаходять цю проблему і погані рішення знову і знову. Це простір? "" а що з "\ n", "\ t" або яким-небудь символом пробілу unicode, якого ви ніколи не бачили, ні в якій невеликій частині, тому що він невидимий. Поки ви можете піти

Слабке рішення

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

Якщо вам коли-небудь потрібно похизуватися реальністю, подивіться відео WWDC на рядках або датах. Коротше кажучи, майже завжди краще дозволити Apple вирішити подібну життєву задачу.

Надійне рішення: Використовуйте NSCharacterSet

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

NSCharacterSet пробіли

Повертає набір символів, що містить символи в загальній категорії Unicode Zs та ТАБУЛЯЦІЇ ХАРАКТЕРІВ (U + 0009).

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

2
Домовились. Перше, що трапилося мені після того, як я побачив відповіді, розділені на "", це: Що станеться, якщо текст вводу містить кілька послідовних пробілів? Що робити, якщо на ньому є вкладки? Простір повної ширини (CJK)? і т. д.
Nicolas Miari

31

У 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 the result is Array.
//Direct single 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

let line = "BLANCHE:   I don't want realism. I want magic!"
print(line.split(separator: " "))
// Prints "["BLANCHE:", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"

Документація Apple ....

let line = "BLANCHE:   I don't want realism. I want magic!"
print(line.split(separator: " "))
// Prints "["BLANCHE:", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"

print(line.split(separator: " ", maxSplits: 1))//This can split your string into 2 parts
// Prints "["BLANCHE:", "  I don\'t want realism. I want magic!"]"

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.
// Prints "["BLANCHE:", "", "", "I", "don\'t", "want", "realism.", "I", "want", "magic!"]"

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

23

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

Приклад: let s = "hi, hello" let a = s.split(separator: ",") print(a)

Тепер у вас з'явився масив з "привіт" і "привіт".


Зауважте, що це не повертає масив String, а масив Substring, який незручно використовувати.
Лірик

19

Оновлення для Swift 5 та найпростіший спосіб

let paragraph = "Bob hit a ball, the hit BALL flew far after it was hit. Hello! Hie, How r u?"

let words = paragraph.components(separatedBy: [",", " ", "!",".","?"])

Це відбитки,

["Боб", "удар", "а", "м'яч", "", "той", "удар", "БОЛЬ", "полетів", "далеко", "після", "це", "був "," хіт "," "," Привіт "," "," Hie "," "," Як "," r "," u "," "]

Однак якщо ви хочете відфільтрувати порожній рядок,

let words = paragraph.components(separatedBy: [",", " ", "!",".","?"]).filter({!$0.isEmpty})

Вихід,

["Боб", "удар", "а", "м'яч", "той", "удар", "кулька", "полетів", "далеко", "після", "це", "було", " хіт "," Привіт "," Хі "," Як "," г "," і "]

Але переконайтесь, що Фундація імпортується


17

Швидкий 3

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

15

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 .


13

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

9

У мене був сценарій, коли в рядку, який я хочу розділити, може бути декілька керуючих символів. Замість того, щоб підтримувати масив таких, я просто дозволю 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
Я б сказав, що це близько до статусу "не відповідь", оскільки це здебільшого коментар до існуючих відповідей. Але це вказує на щось важливе.
рикстер

8

Більшість з цих відповідей передбачає , що введення містить пробіл - НЕ біле простір і єдиний простір в цьому. Якщо ви можете сміливо зробити це припущення, то прийнята відповідь (від Беннета) є досить елегантною, а також методом, з яким я буду їздити, коли зможу.

Коли ми не можемо зробити це припущення, більш надійне рішення повинно охопити наступні ситуації, на які більшість відповідей тут не враховується:

  • вкладки / нові рядки / пробіли (пробіли), включаючи повторювані символи, що
  • провідна / задні пробіли
  • Символи нового рядка Apple / Linux ( \n) та Windows ( \r\n)

Для покриття цих випадків це рішення використовує регулярний вираз для конвертації всіх пробілів (включаючи повторювані символи та символи нового рядка Windows) в єдиний пробіл, обрізки, а потім розбиття на один пробіл:

Швидкий 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])

6

Кроки для розділення рядка на масив у Swift 4.

  1. призначити рядок
  2. на основі @ розщеплення.

Примітка: variaName.components (sepaBy: "розділити ключове слово")

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)

4

Швидкий 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

3

Скажімо, у вас є змінна назва "Hello World", і якщо ви хочете розділити її і зберегти на дві різні змінні, ви можете використовувати так:

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

3

Тільки відповідь splitправильна, ось різниця для більш ніж 2 пробілів.

var temp = "Hello world     ni hao"
let arr  = temp.components(separatedBy: .whitespacesAndNewlines)
// ["Hello", "world", "", "", "", "", "ni", "hao"]
let arr2 = temp.components(separatedBy: " ")
// ["Hello", "world", "", "", "", "", "ni", "hao"]
let arr3 = temp.split(whereSeparator: {$0 == " "})
// ["Hello", "world", "ni", "hao"]

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

Xcode 7,2 (7C68)


2

Swift 2.2 Поводження з помилками та з великої літери Додано рядки:

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

Обробка струн все ще є проблемою у Swift, і вона суттєво змінюється, як видно з інших відповідей. Сподіваємось, все впорядковується, і це стає простішим. Так можна зробити з поточною версією Swift 3.0 з декількома символами розділення.

Швидкий 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)

2

Я шукав пухкий спліт, наприклад PHP, explodeде порожні послідовності включені в результуючий масив, це працювало для мене:

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

Вихід:

["First", ""]

2

Це дає масив розділених частин безпосередньо

var fullNameArr = fullName.components(separatedBy:" ")

тоді ви можете використовувати так,

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


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]

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", "--"]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.