Dividere una stringa in un array in Swift?


688

Di 'che ho una stringa qui:

var fullName: String = "First Last"

Voglio dividere la base di stringhe su uno spazio bianco e assegnare i valori alle rispettive variabili

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

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

Inoltre, a volte gli utenti potrebbero non avere un cognome.


13
Ciao, non ho il mio Mac da controllare. Ma puoi provare 'fullName.componentsSeparatedByString (string: "")' Non copiare e incollare, usa la funzione di completamento automatico, in modo da ottenere la funzione giusta.
David Gölzhäuser,

Se stai dividendo solo per un carattere, usa anche le fullName.utf8.split( <utf-8 character code> )opere (sostituisci .utf8con .utf16per UTF-16). Ad esempio, è possibile dividere su +usandofullName.utf8.split(43)
Jojodmo il

Inoltre, a volte i cognomi hanno degli spazi, come in "Daphne du Maurier" o "Charles de Lint"
Berry,

Risposte:


784

Il modo rapido è usare la splitfunzione globale , in questo modo:

var fullName = "First Last"
var fullNameArr = split(fullName) {$0 == " "}
var firstName: String = fullNameArr[0]
var lastName: String? = fullNameArr.count > 1 ? fullNameArr[1] : nil

con Swift 2

In Swift 2 l'uso della divisione diventa un po 'più complicato a causa dell'introduzione del tipo CharacterView interno. Ciò significa che String non adotta più i protocolli SequenceType o CollectionType e devi invece utilizzare la .charactersproprietà per accedere a una rappresentazione di tipo CharacterView di un'istanza String. (Nota: CharacterView adotta i protocolli SequenceType e 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
Nei miei test, ComponentsSeparatedByString è in genere significativamente più veloce, soprattutto quando si tratta di stringhe che richiedono la divisione in molti pezzi. Ma per l'esempio elencato dall'OP, entrambi dovrebbero essere sufficienti.
Casey Perkins,

9
A partire da Xcode 6.2b3 è possibile utilizzare la suddivisione come split("a:b::c:", {$0 == ":"}, maxSplit: Int.max, allowEmptySlices: false).
Pascal,

14
Ricorda solo che devi ancora usare il vecchio componentsSeparatedByString()metodo se il tuo separatore è qualcosa di più lungo di un singolo carattere. E bello come sarebbe dire let (firstName, lastName) = split(fullName) {$0 == ' '}, che non funziona, purtroppo.
NRitH,

3
@Kashif allora potresti usare split("a,b;c,d") {$0 == "," || $0 == ";"}osplit("a,b;c,d") {contains(",;", $0)}
Ethan

4
Il codice corretto per Xcode 7.0 è lasciare fullNameArr = fullName.characters.split {$ 0 == ""} .map (String.init). Ho provato a modificare, ma è stato rifiutato.
skagedal,

1016

Basta chiamare il componentsSeparatedByStringmetodo sul tuofullName

import Foundation

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

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

Aggiornamento per Swift 3+

import Foundation

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

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

3
Si noti che questo è in realtà un sottostante NSString(Swift li scambia automaticamente durante l'importazione Foundation).
Can

1
Questo non è più il caso di Swift 1.2, in cui Apple non converte più la stringa di Swift in NSString automaticamente.
elcuco,

6
Questa risposta funziona in Xcode 7 beta 4 e Swift 2.0. Xcode ora completa automaticamente i metodi Foundation su oggetti Swift String senza digitare il cast su un NSString, cosa che non è il caso in Xcode 6.4 con Swift 1.2.
Andrew,

1
Non ha funzionato nel REPL fino a quando non ho importato Foundation.
Velizar Hristov,

1
Funziona esattamente come previsto (cioè fullNameArr è un [String]) in Xcode 7.2.
Jon Cox,

185

Il metodo più semplice per farlo è utilizzando componentiSeparatedBy:

Per 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]

Per 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]

È documentato da qualche parte, Maury? Cosa succede se devo dividere qualcosa di diverso da un singolo personaggio?
NRitH,

10
@NRitH considera .componentsSeparatedByCharactersInSet(.whitespaceAndNewlineCharacterSet())
rmp251

@Crashalot ci sono due funzioni: componentsSeparatedByStringecomponentsSeparatedByCharactersInSet
rmp251

132

Swift Dev. 4.0 (24 maggio 2017)

Una nuova funzione splitin Swift 4 ( Beta ).

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

Produzione:

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

Accesso ai valori:

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

Xcode 8.1 / Swift 3.0.1

Ecco il modo in cui più delimitatori con array.

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

Produzione:

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

8
Assicurati di aggiungere import Foundationalla classe in cui lo stai utilizzando. #SavedYouFiveMinutes
Adrian

4
Attenzione (Swift 4): se si dispone di una stringa simile let a="a,,b,c"e si utilizza, per impostazione predefinita a.split(separator: ",")si ottiene un array come ["a", "b", c"]. Questo può essere modificato usando omittingEmptySubsequences: falsequale è vero per impostazione predefinita.
OderWat,

2
Qualche divisione multi-carattere in Swift 4+?
pkamb,

57

Swift 4 o successivo

Se hai solo bisogno di formattare correttamente il nome di una persona, puoi usare PersonNameComponentsFormatter .

La classe PersonNameComponentsFormatter fornisce rappresentazioni localizzate dei componenti del nome di una persona, come rappresentato da un oggetto PersonNameComponents. Utilizzare questa classe per creare nomi localizzati quando si visualizzano le informazioni sul nome della persona per l'utente.


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

inserisci qui la descrizione dell'immagine

Modifica / aggiornamento:

Swift 5 o successivo

Per dividere una stringa per caratteri non lettera possiamo usare la nuova proprietà Character isLetter:

let fullName = "First Last"

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

1
@DarrellRoot devi solo mappare le sottostringhefullName.split { $0.isWhitespace }.map(String.init)
Leo Dabus il

2
Adoro quella nuova API, ma tieni presente che restituisce Substrings. Avevo bisogno di stringhe (e volevo dividere gli spazi bianchi in generale), quindi l'ho fatto: let words = line.split{ $0.isWhitespace }.map{ String($0)} grazie a @LeoDabus per la tua versione (il mio commento originale non aveva il codice). Inoltre suggerisco di spostare la versione di Swift 5 all'inizio della risposta.
Darrell Root,

53

In alternativa alla risposta di WMios, puoi anche usare componentsSeparatedByCharactersInSet, che può essere utile nel caso in cui tu abbia più separatori (spazio vuoto, virgola, ecc.).

Con il tuo input specifico:

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

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

Utilizzando più separatori:

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

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

2
La risposta più utile a mio avviso, dal momento che potresti voler consentire la separazione delle stringhe con ,o con ;qualsiasi altro separatore
Chris

49

Swift 4

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

34

Il problema degli spazi bianchi

In generale, le persone reinventano questo problema e le soluzioni sbagliate più e più volte. Questo è uno spazio? "" e che dire di "\ n", "\ t" o qualche carattere di spazio bianco unicode che non hai mai visto, in nessuna piccola parte perché è invisibile. Mentre puoi cavartela

Una soluzione debole

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

Se hai mai bisogno di stringere la presa sulla realtà, guarda un video del WWDC su stringhe o date. In breve, è quasi sempre meglio consentire ad Apple di risolvere questo tipo di compito banale.

Soluzione robusta: utilizzare NSCharacterSet

Il modo per farlo correttamente, IMHO, è di usarlo NSCharacterSetpoiché, come affermato in precedenza, il tuo spazio bianco potrebbe non essere quello che ti aspetti e Apple ha fornito un set di caratteri per lo spazio bianco. Per esplorare i vari set di caratteri forniti, consulta la documentazione per sviluppatori NSCharacterSet di Apple e poi, solo allora, aumenta o costruisci un nuovo set di caratteri se non soddisfa le tue esigenze.

NSCharacterSet spazi bianchi

Restituisce un set di caratteri contenente i caratteri nelle categorie generali Unicode Z e TABOLAZIONE CARATTERI (U + 0009).

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

2
Concordato. La prima cosa che mi è venuta in mente dopo aver visto le risposte divise per "" è: cosa succede se il testo inserito contiene più spazi consecutivi? E se avesse delle schede? Spazio a larghezza intera (CJK)? ecc.
Nicolas Miari,

31

In Swift 4.2 e Xcode 10

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

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

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

Opzione 3

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

Opzione 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!"]"

Con la documentazione 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 semplifica notevolmente la divisione dei caratteri, basta usare la nuova funzione di divisione per le stringhe.

Esempio: let s = "hi, hello" let a = s.split(separator: ",") print(a)

Ora hai un array con 'ciao' e 'ciao'.


Si noti che questo non restituisce una matrice di String, ma una matrice di Sottostringa che è scomoda da usare.
Lirik,

19

Aggiornamento per Swift 5 e il modo più semplice

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: [",", " ", "!",".","?"])

Questo stampa,

["Bob", "hit", "a", "ball", "", "the", "hit", "BALL", "fly", "far", "after", "it", "was "," hit "," "," Hello "," "," Hie "," "," How "," r "," u "," "]

Tuttavia, se desideri filtrare una stringa vuota,

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

Produzione,

["Bob", "hit", "a", "ball", "the", "hit", "BALL", "fly", "far", "after", "it", "was", " premi "," Ciao "," Hie "," How "," r "," u "]

Ma assicurati che Foundation sia importato


17

Swift 3

let line = "AAA    BBB\t CCC"
let fields = line.components(separatedBy: .whitespaces).filter {!$0.isEmpty}
  • Restituisce tre corde AAA, BBBeCCC
  • Filtra i campi vuoti
  • Gestisce più spazi e caratteri di tabulazione
  • Se vuoi gestire nuove linee, sostituiscile .whitespacescon.whitespacesAndNewlines

15

Swift 4, Xcode 10 e iOS 12 Update funzionano al 100%

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

Consulta la documentazione di Apple qui per ulteriori informazioni.


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

Lunga via:

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

Ho avuto uno scenario in cui più caratteri di controllo possono essere presenti nella stringa che voglio dividere. Piuttosto che mantenere una serie di questi, ho lasciato che Apple gestisse quella parte.

Quanto segue funziona con Swift 3.0.1 su iOS 10:

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

8

Ho trovato un caso interessante, quello

metodo 1

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

Quando ho usato questo comando per dividere un simbolo dai dati caricati dal server , può dividere durante il test nel simulatore e sincronizzarsi con il dispositivo di test, ma non si divide in app di pubblicazione e Ad hoc

Mi ci vuole molto tempo per tenere traccia di questo errore, potrebbe essere maledetto da una versione di Swift o da una versione di iOS o nessuno dei due

Non si tratta anche del codice HTML, poiché provo a stringByRemovingPercentEncoding e non funziona ancora

aggiunta 10/10/2015

in Swift 2.0 questo metodo è stato modificato in

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

metodo 2

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

Quando ho usato questo comando, è possibile dividere correttamente gli stessi dati caricati dal server


Conclusione, suggerisco davvero di usare il metodo 2

string.componentsSeparatedByString("")

1
Direi che questo è vicino allo stato "non una risposta", in quanto è principalmente un commento alle risposte esistenti. Ma sta sottolineando qualcosa di importante.
rickster,

8

La maggior parte di queste risposte presuppone che l'input contenga uno spazio, non uno spazio bianco , e un singolo spazio. Se puoi tranquillamente fare questa ipotesi, allora la risposta accettata (da Bennett) è piuttosto elegante e anche il metodo che seguirò quando posso.

Quando non riusciamo a fare questo presupposto, una soluzione più solida deve coprire le seguenti considerazioni che la maggior parte delle risposte qui non considera:

  • tab / newline / spazi (spazi bianchi), inclusi i caratteri ricorrenti
  • spazi iniziali / finali
  • Caratteri newline di Apple / Linux ( \n) e Windows ( \r\n)

Per coprire questi casi, questa soluzione utilizza regex per convertire tutti gli spazi bianchi (inclusi i caratteri ricorrenti e di nuova riga di Windows) in un singolo spazio, ritaglia, quindi si divide per un singolo spazio:

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

O senza chiusure puoi fare proprio questo in Swift 2:

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

6

Passaggi per dividere una stringa in un array in Swift 4.

  1. assegnare una stringa
  2. basato su @ split.

Nota: variabileNome.componenti (separateDa: "parola chiave divisa")

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

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

Produzione

loremipsum
dolorsant
amet:
total: 3

3

Supponiamo che tu abbia una variabile chiamata "Hello World" e se vuoi dividerla e memorizzarla in due diverse variabili puoi usare così:

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

3

Questo dà una serie di parti scisse direttamente

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

allora puoi usare così,

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

3

Solo la splitrisposta è corretta, ecco la differenza per più di 2 spazi.

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 Error Handling & capitalizedString Aggiunto:

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

La gestione delle stringhe è ancora una sfida in Swift e continua a cambiare in modo significativo, come puoi vedere dalle altre risposte. Spero che le cose si sistemino e diventa più semplice. Questo è il modo di farlo con l'attuale versione 3.0 di Swift con più caratteri di separazione.

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)

2

Stavo cercando una suddivisione approssimativa , come PHP in explodecui sono incluse sequenze vuote nell'array risultante, questo ha funzionato per me:

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

Produzione:

["First", ""]

1

Questo è cambiato di nuovo in Beta 5. Weee! Ora è un metodo su CollectionType

Vecchio:

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

Nuovo:

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

Note di rilascio delle mele


1

Per 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]

1

Ecco un algoritmo che ho appena creato, che dividerà uno Stringper qualsiasi Characterdall'array e se si desidera mantenere le sottostringhe con caratteri divisi, è possibile impostare il swallowparametro sutrue .

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

Esempio:

"test text".splitBy([" "]) // ["test", "text"]
"test++text--".splitBy(["+", "-"], swallow: true) // ["test", "++" "text", "--"]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.