Convertir Swift string a array

133

¿Cómo puedo convertir una cadena "Hola" en una matriz ["H", "e", "l", "l", "o"] en Swift?

En Objective-C he usado esto:

NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[myString length]];
for (int i=0; i < [myString length]; i++) {
    NSString *ichar  = [NSString stringWithFormat:@"%c", [myString characterAtIndex:i]];
    [characters addObject:ichar];
}
Mr.KLD
fuente

Respuestas:

339

Es aún más fácil en Swift:

let string : String = "Hello 🐶🐮 🇩🇪"
let characters = Array(string)
println(characters)
// [H, e, l, l, o,  , 🐶, 🐮,  , 🇩🇪]

Esto usa los hechos que

  • una Arraypuede ser creado a partir de una SequenceType, y
  • Stringse ajusta al SequenceTypeprotocolo y su generador de secuencia enumera los caracteres.

Y dado que las cadenas Swift tienen soporte completo para Unicode, esto funciona incluso con caracteres fuera del "Plano multilingüe básico" (como 🐶) y con grupos de grafemas extendidos (como 🇩🇪, que en realidad está compuesto por dos escalares Unicode).


Actualización: a partir de Swift 2, String ya no se ajusta SequenceType, pero la characterspropiedad proporciona una secuencia de los caracteres Unicode:

let string = "Hello 🐶🐮 🇩🇪"
let characters = Array(string.characters)
print(characters)

Esto también funciona en Swift 3 .


Actualización: a partir de Swift 4, String es (de nuevo) una colección de sus Characters:

let string = "Hello 🐶🐮 🇩🇪"
let characters = Array(string)
print(characters)
// ["H", "e", "l", "l", "o", " ", "🐶", "🐮", " ", "🇩🇪"]
Martin R
fuente
1
¿Tienes alguna idea de por qué intentar unir ( let joined = ", ".join(characters);) la matriz da como resultado un 'String' is not identical to 'Character'error?
Mohamad
3
@Mohamad: enumerar una cadena produce una secuencia de caracteres, pero ", ".join(...)espera una serie de cadenas. La respuesta de devxoul a continuación muestra cómo podría dividirse en una serie de cadenas.
Martin R
2
@Fonix: characterses una colección y una vista de los caracteres de las cadenas. Crear una matriz a partir de los personajes hace una copia. - Por supuesto, puede acceder a los personajes directamente: for i in string.characters.indices { print(string.characters[i]) }o simplementefor c in string.characters { print(c) }
Martin R
2
@Fonix: ... Por otro lado, la indexación aleatoria en cadenas puede ser lenta y puede ser ventajoso crear una matriz con todos los caracteres una vez. Ejemplo: stackoverflow.com/questions/40371929/… .
Martin R
2
@DaniSpringer: Swift 4 está actualmente en beta, necesitará Xcode 9 beta: developer.apple.com/swift/resources .
Martin R
102

Editar (Swift 4)

En Swift 4, no tiene que usar characterspara usar map(). Solo hazlo map()en String.

let letters = "ABC".map { String($0) }
print(letters) // ["A", "B", "C"]
print(type(of: letters)) // Array<String>

O si prefiere más corto: "ABC".map(String.init)(2 bytes 😀)

Editar (Swift 2 y Swift 3)

En Swift 2 y Swift 3, puede usar la map()función a la characterspropiedad.

let letters = "ABC".characters.map { String($0) }
print(letters) // ["A", "B", "C"]

Original (Swift 1.x)

La respuesta aceptada no parece ser la mejor, porque la conversión de secuencia Stringno es una Stringsecuencia, sino que Character:

$ swift
Welcome to Swift!  Type :help for assistance.
  1> Array("ABC")
$R0: [Character] = 3 values {
  [0] = "A"
  [1] = "B"
  [2] = "C"
}

Esto a continuación funciona para mí:

let str = "ABC"
let arr = map(str) { s -> String in String(s) }

La referencia para una función global map()está aquí: http://swifter.natecook.com/func/map/

devxoul
fuente
12
Ligeramente más corto:arr = map(str) { String($0) }
Martin R
1
Utilice el Arrayinicializador en su lugar:Array("ABC".characters)
chrisamanse
1
@chrisamanse, no hay diferencia entre "ABC".charactersy Array("ABC".characters).
devxoul
2
Es diferente en Swift 3. "ABC".charactersdevuelve un tipo String.CharacterView. Para convertirlo en una matriz, específicamente de tipo, [Character]tendría que usar el Arrayinicializador.
chrisamanse
2
@chrisamanse Oh, no lo sabía. Estaba equivocado. Gracias por mencionarlo. Por cierto, pretendía en [String]lugar de [Character]porque op quería una matriz de cadenas :)
devxoul
22

También existe esta útil función en String: components (separados por: String)

let string = "1;2;3"
let array = string.components(separatedBy: ";")
print(array) // returns ["1", "2", "3"]

Funciona bien para manejar cadenas separadas por un carácter como ";" o incluso "\ n"

Frédéric Adda
fuente
8

Actualizado para Swift 4

Aquí hay 3 formas.

//array of Characters
let charArr1 = [Character](myString)

//array of String.element
let charArr2 = Array(myString)

for char in myString {
  //char is of type Character
}

En algunos casos, lo que la gente realmente quiere es una forma de convertir una cadena en una serie de pequeñas cadenas con 1 longitud de caracteres cada una. Aquí hay una forma súper eficiente de hacer eso:

//array of String
var strArr = myString.map { String($0)}

Swift 3

Aquí hay 3 formas.

let charArr1 = [Character](myString.characters)
let charArr2 = Array(myString.characters)
for char in myString.characters {
  //char is of type Character
}

En algunos casos, lo que la gente realmente quiere es una forma de convertir una cadena en una serie de pequeñas cadenas con 1 longitud de caracteres cada una. Aquí hay una forma súper eficiente de hacer eso:

var strArr = myString.characters.map { String($0)}

O puede agregar una extensión a String.

extension String {
   func letterize() -> [Character] {
     return Array(self.characters)
  }
}

Entonces puedes llamarlo así:

let charArr = "Cat".letterize()
ScottyBlades
fuente
4
    let string = "hell0"
    let ar = Array(string.characters)
    print(ar)
William Hu
fuente
No hubo cambios entre Swift 2 y 3 con respecto a este problema. Esta solución es idéntica a la versión Swift 2 en stackoverflow.com/a/25921323/1187415 .
Martin R
3

La respuesta de Martin R es el mejor enfoque, y como dijo, porque String cumple con el protocolo SquenceType, también puede enumerar una cadena, obteniendo cada carácter en cada iteración.

let characters = "Hello"
var charactersArray: [Character] = []

for (index, character) in enumerate(characters) {
    //do something with the character at index
    charactersArray.append(character)
}

println(charactersArray)
Alberto Barrera
fuente
2
O simplemente for character in characters { charactersArray.append(character)}sin elenumeration()
Tieme
3

En Swift 4, como Stringes una colección de Character, debe usarmap

let array1 = Array("hello") // Array<Character>
let array2 = Array("hello").map({ "\($0)" }) // Array<String>
let array3 = "hello".map(String.init) // Array<String>
onmyway133
fuente
3

Una manera fácil de hacer esto es a mapla variable y devolver cada uno Charactercomo String:

let someText = "hello"

let array = someText.map({ String($0) }) // [String]

La salida debería ser ["h", "e", "l", "l", "o"].

atolita
fuente
1

También puedes crear una extensión:

var strArray = "Hello, playground".Letterize()

extension String {
    func Letterize() -> [String] {
        return map(self) { String($0) }
    }
}
fabrizioM
fuente
1
func letterize() -> [Character] {
    return Array(self.characters)
}
Piotr Pszczółkowski
fuente
2
¿Puede proporcionar más información por qué esto funcionará? :)
pix
1
@pix Creo que se refería a esto como una función definida en una extensión de String. Agregaré eso a mi respuesta.
ScottyBlades
1

para la función en Cadena: componentes (separados por: Cadena)

en Swift 5.1

cambiar a:

string.split(separator: "/")

Panda gordo
fuente