ios - Swift: Divide una cadena en una matriz
substring swift 3 (30)
El tema del espacio en blanco.
En general, las personas reinventan este problema y las malas soluciones una y otra vez. ¿Es este un espacio? "" y qué pasa con "/ n", "/ t" o algún carácter de espacio en blanco Unicode que nunca has visto, en gran parte porque es invisible. Mientras que usted puede salirse con la suya
Una solución débil
import Foundation
let pieces = "Mary had little lamb".componentsSeparatedByString(" ")
Si alguna vez necesitas agitarte con la realidad, mira un video de la WWDC en cadenas o fechas. En resumen, casi siempre es mejor permitir que Apple resuelva este tipo de tarea mundana.
Solución robusta: utilizar NSCharacterSet
La manera de hacerlo correctamente, en mi humilde opinión, es usar NSCharacterSet
ya que como se indicó anteriormente, su espacio en blanco podría no ser lo que usted espera y Apple ha proporcionado un conjunto de caracteres de espacio en blanco. Para explorar los diversos conjuntos de caracteres proporcionados, consulte la documentación para desarrolladores de NSCharacterSet de Apple y luego, solo entonces, aumente o construya un nuevo conjunto de caracteres si no se ajusta a sus necesidades.
NSCharacterSet espacios en blanco
Devuelve un conjunto de caracteres que contiene los caracteres de la Categoría General Unicode y la TABULACIÓN DE PERSONAJES (U + 0009).
let longerString: String = "This is a test of the character set splitting system"
let components = longerString.components(separatedBy: .whitespaces)
print(components)
Digamos que tengo una cuerda aquí:
var fullName: String = "First Last"
Quiero dividir la base de la cadena en el espacio en blanco y asignar los valores a sus respectivas variables
var fullNameArr = // something like: fullName.explode(" ")
var firstName: String = fullNameArr[0]
var lastName: String? = fullnameArr[1]
Además, a veces los usuarios pueden no tener un apellido.
Aquí hay un algoritmo que acabo de construir, que dividirá una String
por cualquier Character
de la matriz y, si hay algún deseo de mantener las subcadenas con caracteres divididos, se podría establecer el parámetro swallow
en 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
}
}
}
}
Ejemplo:
"test text".splitBy([" "]) // ["test", "text"]
"test++text--".splitBy(["+", "-"], swallow: true) // ["test", "++" "text", "--"]
Como alternativa a la respuesta de WMios, también puede usar componentsSeparatedByCharactersInSet
, que puede ser útil en caso de que tenga más separadores (espacio en blanco, coma, etc.).
Con su entrada específica:
let separators = NSCharacterSet(charactersInString: " ")
var fullName: String = "First Last";
var words = fullName.componentsSeparatedByCharactersInSet(separators)
// words contains ["First", "Last"]
Usando múltiples separadores:
let separators = NSCharacterSet(charactersInString: " ,")
var fullName: String = "Last, First Middle";
var words = fullName.componentsSeparatedByCharactersInSet(separators)
// words contains ["Last", "First", "Middle"]
Digamos que tienes una variable llamada "Hello World" y si quieres dividirla y almacenarla en dos variables diferentes, puedes usar así:
var fullText = "Hello World"
let firstWord = fullText.text?.components(separatedBy: " ").first
let lastWord = fullText.text?.components(separatedBy: " ").last
El manejo de cuerdas sigue siendo un desafío en Swift y sigue cambiando significativamente, como puede ver en otras respuestas. Esperemos que las cosas se calmen y se vuelvan más simples. Esta es la forma de hacerlo con la versión 3.0 actual de Swift con varios caracteres separadores.
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)
En Swift 4.1 y Xcode 9.4.1
//This is your str
let str = "This is my String" //Here replace with your string
Opción 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!)
opcion 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)
Opcion 3
let arr = str.split {$0 == " "}
print(arr)
Opcion 4
Por documentación de 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))
Encontré un caso interesante, que
Método 1
var data:[String] = split( featureData ) { $0 == "/u{003B}" }
Cuando usé este comando para dividir algún símbolo de los datos que se cargaron desde el servidor , se puede dividir mientras se prueba en el simulador y se sincroniza con el dispositivo de prueba, pero no se dividirá en la aplicación de publicación, y Ad Hoc
Me lleva mucho tiempo rastrear este error. Puede que haya sido maldecido por alguna versión Swift, una versión iOS o ninguna.
Tampoco se trata del código HTML, ya que intento stringByRemovingPercentEncoding y todavía no funciona
Además 10/10/2015
en Swift 2.0 este método ha sido cambiado a
var data:[String] = featureData.split {$0 == "/u{003B}"}
método 2
var data:[String] = featureData.componentsSeparatedByString("/u{003B}")
Cuando usé este comando, puede dividir los mismos datos que se cargan desde el servidor correctamente
Conclusión, realmente sugiero utilizar el método 2.
string.componentsSeparatedByString("")
Espero que esto sea útil
Swift 4: Divide una cadena en una matriz. Paso 1: asignar cadena. paso 2: basado en @ spliting. Nota: variableName.components (separado por: "palabra clave dividida")
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)
Estaba buscando una división débil , como la explode
de PHP donde se incluyen secuencias vacías en la matriz resultante, esto funcionó para mí:
"First ".split(separator: " ", maxSplits: 1, omittingEmptySubsequences: false)
Salida:
["First", ""]
Esto ha cambiado de nuevo en Beta 5. Weee! Ahora es un método en CollectionType
Antiguo:
var fullName = "First Last"
var fullNameArr = split(fullName) {$0 == " "}
Nuevo:
var fullName = "First Last"
var fullNameArr = fullName.split {$0 == " "}
La forma rápida es usar la función de split
global, así:
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
En Swift 2, el uso de la división se vuelve un poco más complicado debido a la introducción del tipo de CharacterView interno. Esto significa que String ya no adopta los protocolos SequenceType o CollectionType y en su lugar debe usar la propiedad .characters
para acceder a una representación de tipo CharacterView de una instancia de String. (Nota: CharacterView adopta los protocolos SequenceType y 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
La mayoría de estas respuestas asumen que la entrada contiene un espacio, no un espacio en blanco , y un solo espacio. Si puede hacer esa suposición de manera segura, entonces la respuesta aceptada (de Bennett) es bastante elegante y también el método con el que iré cuando pueda.
Cuando no podemos hacer esa suposición, una solución más robusta debe cubrir las siguientes afirmaciones que la mayoría de las respuestas aquí no consideran:
- pestañas / nuevas líneas / espacios (espacios en blanco), incluidos los caracteres recurrentes
- espacios en blanco iniciales / finales
- Caracteres de nueva línea de Apple / Linux (
/n
) y Windows (/r/n
)
Para cubrir estos casos, esta solución usa expresiones regulares para convertir todos los espacios en blanco (incluidos los caracteres recurrentes y los caracteres de nueva línea de Windows) en un solo espacio, recorta y luego se divide por un solo espacio:
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"]
No he encontrado la solución que maneje nombres con 3 o más componentes y admita versiones anteriores de 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)
}
}
Casos de prueba aprobados:
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)
}
O sin cierres puedes hacer esto en Swift 2:
let fullName = "First Last"
let fullNameArr = fullName.characters.split(" ")
let firstName = String(fullNameArr[0])
Para 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]
Simplemente llame al método componentsSeparatedByString
en su fullName
import Foundation
var fullName: String = "First Last"
let fullNameArr = fullName.componentsSeparatedByString(" ")
var firstName: String = fullNameArr[0]
var lastName: String = fullNameArr[1]
Actualización para Swift 3+
import Foundation
let fullName = "First Last"
let fullNameArr = fullName.components(separatedBy: " ")
let name = fullNameArr[0]
let surname = fullNameArr[1]
Swift 4 hace que sea mucho más fácil dividir caracteres, solo use la nueva función de división para Cuerdas.
Ejemplo: let s = "hi, hello" let a = s.split(separator: ",") print(a)
Ahora tienes una matriz con ''hola'' y ''hola''.
Tuve un escenario en el que varios caracteres de control pueden estar presentes en la cadena que quiero dividir. En lugar de mantener una serie de estos, simplemente dejo que Apple maneje esa parte.
Los siguientes trabajos funcionan con Swift 3.0.1 en iOS 10:
let myArray = myString.components(separatedBy: .controlCharacters)
El método más fácil para hacer esto es usar componentsSeparatedBy:
Para 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]
Para 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]
Actualización de Swift 4, Xcode 10 e iOS 12 100% funcionando
let fullName = "First Last"
let fullNameArr = fullName.components(separatedBy: " ")
let firstName = fullNameArr[0] //First
let lastName = fullnameArr[1] //Last
Consulte la documentación de Apple aquí para obtener más información.
Según Swift 2.2
Solo escribe el código de 2 líneas y obtendrás la cadena dividida.
let fullName = "FirstName LastName"
var splitedFullName = fullName.componentsSeparatedByString(" ")
print(splitedFullName[0])
print(splitedFullName[1])
Disfrutar. :)
Swift 2.2 Error Handling & capitalizedString Añadido:
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
}
Swift 3
let line = "AAA BBB/t CCC"
let fields = line.components(separatedBy: .whitespaces).filter {!$0.isEmpty}
- Devuelve tres cadenas
AAA
,BBB
yCCC
- Filtra los campos vacíos
- Maneja múltiples espacios y caracteres de tabulación.
- Si desea manejar nuevas líneas, reemplace
.whitespaces
con.whitespacesAndNewlines
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)")
Salida
loremipsum
dolorsant
amet:
total: 3
Swift 4
let words = "these words will be elements in an array".components(separatedBy: " ")
Swift Dev. 4.0 (24 de mayo de 2017)
Una nueva función split
en Swift 4 ( Beta ).
import Foundation
let sayHello = "Hello Swift 4 2017";
let result = sayHello.split(separator: " ")
print(result)
Salida:
["Hello", "Swift", "4", "2017"]
Valores de acceso:
print(result[0]) // Hello
print(result[1]) // Swift
print(result[2]) // 4
print(result[3]) // 2017
Xcode 8.1 / Swift 3.0.1
Esta es la forma de múltiples delimitadores con matriz.
import Foundation
let mathString: String = "12-37*2/5"
let numbers = mathString.components(separatedBy: ["-", "*", "/"])
print(numbers)
Salida:
["12", "37", "2", "5"]
Xcode 8.0 / Swift 3
let fullName = "First Last"
var fullNameArr = fullName.components(separatedBy: " ")
var firstname = fullNameArr[0] // First
var lastname = fullNameArr[1] // Last
Largo camino:
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
Xcode 9 Swift 4 o Xcode 8.2.1 • Swift 3.0.2
Si solo necesita formatear correctamente el nombre de una persona, puede usar PersonNameComponentsFormatter .
La clase PersonNameComponentsFormatter proporciona representaciones localizadas de los componentes del nombre de una persona, como lo representa un objeto PersonNameComponents. Utilice esta clase para crear nombres localizados cuando muestre información del nombre de la persona al usuario.
// 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."
}
let str = "one two"
let strSplit = str.characters.split(" ").map(String.init) // returns ["one", "two"]
Xcode 7.2 (7C68)
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"
- No permitir el mismo nombre y apellido
- Si un nombre completo no es válido, tome el valor de marcador de posición "John Doe"