Convertir la chaîne Swift en tableau

133

Comment puis-je convertir une chaîne "Hello" en un tableau ["H", "e", "l", "l", "o"] dans Swift?

En Objective-C, j'ai utilisé ceci:

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];
}
Monsieur KLD
la source

Réponses:

339

C'est encore plus simple dans Swift:

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

Cela utilise les faits qui

  • un Arraypeut être créé à partir d'un SequenceType, et
  • Stringest conforme au SequenceTypeprotocole et son générateur de séquence énumère les caractères.

Et comme les chaînes Swift ont un support complet pour Unicode, cela fonctionne même avec des caractères en dehors du "Plan multilingue de base" (comme 🐶) et avec des clusters de graphèmes étendus (tels que 🇩🇪, qui est en fait composé de deux scalaires Unicode).


Mise à jour: à partir de Swift 2, String n'est plus conforme à SequenceType, mais la characterspropriété fournit une séquence de caractères Unicode:

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

Cela fonctionne également dans Swift 3 .


Mise à jour: Depuis Swift 4, String est (encore) une collection de ses Characters:

let string = "Hello 🐶🐮 🇩🇪"
let characters = Array(string)
print(characters)
// ["H", "e", "l", "l", "o", " ", "🐶", "🐮", " ", "🇩🇪"]
Martin R
la source
1
Avez-vous une idée de la raison pour laquelle essayer de join ( let joined = ", ".join(characters);) le tableau entraîne une 'String' is not identical to 'Character'erreur?
Mohamad
3
@Mohamad: l'énumération d'une chaîne produit une séquence de caractères, mais ", ".join(...)attend un tableau de chaînes. La réponse de devxoul ci-dessous montre comment vous pouvez vous diviser en un tableau de chaînes.
Martin R
2
@Fonix: charactersest une collection et une vue sur les chaînes de caractères. La création d'un tableau à partir des caractères fait une copie. - Bien sûr, on peut accéder directement aux personnages: for i in string.characters.indices { print(string.characters[i]) }ou tout simplementfor c in string.characters { print(c) }
Martin R
2
@Fonix: ... D'un autre côté, l'indexation aléatoire dans les chaînes peut être lente et il peut être avantageux de créer un tableau avec tous les caractères une fois. Exemple: stackoverflow.com/questions/40371929/… .
Martin R
2
@DaniSpringer: Swift 4 est actuellement en version bêta, vous aurez besoin de Xcode 9 beta: developer.apple.com/swift/resources .
Martin R
102

Modifier (Swift 4)

Dans Swift 4, vous n'avez pas besoin d'utiliser characterspour utiliser map(). Faites simplement map()sur String.

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

Ou si vous préférez plus court: "ABC".map(String.init)(2 octets 😀)

Modifier (Swift 2 et Swift 3)

Dans Swift 2 et Swift 3, vous pouvez utiliser la map()fonction pour la characterspropriété.

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

Original (Swift 1.x)

La réponse acceptée ne semble pas être la meilleure, car la conversion de séquence Stringn'est pas une Stringséquence, mais Character:

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

Ceci ci-dessous fonctionne pour moi:

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

La référence pour une fonction globale map()est ici: http://swifter.natecook.com/func/map/

devxoul
la source
12
Légèrement plus court:arr = map(str) { String($0) }
Martin R
1
Utilisez Arrayplutôt l' initialiseur:Array("ABC".characters)
chrisamanse
1
@chrisamanse, Il n'y a pas de différence entre "ABC".characterset Array("ABC".characters).
devxoul
2
C'est différent dans Swift 3. "ABC".charactersrenvoie un type String.CharacterView. Pour le convertir en un tableau, spécifiquement de type [Character], vous devez utiliser l' Arrayinitialiseur dessus.
chrisamanse
2
@chrisamanse Oh, je ne le savais pas. J'avais tort. Merci de l'avoir signalé. Au fait, je voulais [String]plutôt [Character]parce que op voulait un tableau de chaînes :)
devxoul
22

Il existe également cette fonction utile sur String: components (sharedBy: String)

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

Fonctionne bien pour traiter les chaînes séparées par un caractère comme ";" ou même "\ n"

Frédéric Adda
la source
8

Mis à jour pour Swift 4

Voici 3 façons.

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

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

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

Dans certains cas, ce que les gens veulent vraiment, c'est un moyen de convertir une chaîne en un tableau de petites chaînes de 1 caractère chacune. Voici un moyen très efficace de le faire:

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

Swift 3

Voici 3 façons.

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

Dans certains cas, ce que les gens veulent vraiment, c'est un moyen de convertir une chaîne en un tableau de petites chaînes de 1 caractère chacune. Voici un moyen très efficace de le faire:

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

Ou vous pouvez ajouter une extension à String.

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

Ensuite, vous pouvez l'appeler comme ceci:

let charArr = "Cat".letterize()
ScottyBlades
la source
4
    let string = "hell0"
    let ar = Array(string.characters)
    print(ar)
William Hu
la source
Il n'y a eu aucun changement entre Swift 2 et 3 en ce qui concerne ce problème. Cette solution est identique à la version Swift 2 dans stackoverflow.com/a/25921323/1187415 .
Martin R
3

La réponse de Martin R est la meilleure approche, et comme il l'a dit, comme String est conforme au protocole SquenceType, vous pouvez également énumérer une chaîne, en obtenant chaque caractère à chaque itération.

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
la source
2
Ou tout simplement for character in characters { charactersArray.append(character)}sans leenumeration()
Tieme
3

Dans Swift 4, tout comme Stringune collection de Character, vous devez utilisermap

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

Pour ce faire, vous pouvez facilement accéder à mapla variable et renvoyer chacun Charactersous la forme d'un String:

let someText = "hello"

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

La sortie doit être ["h", "e", "l", "l", "o"].

atolite
la source
1

Vous pouvez également créer une extension:

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

extension String {
    func Letterize() -> [String] {
        return map(self) { String($0) }
    }
}
fabrizioM
la source
1
func letterize() -> [Character] {
    return Array(self.characters)
}
Piotr Pszczółkowski
la source
2
Pouvez-vous fournir plus d'informations sur les raisons pour lesquelles cela fonctionnera? :)
pix
1
@pix Je pense qu'il voulait que cela soit une fonction définie dans une extension de String. J'ajouterai cela à ma réponse.
ScottyBlades
1

pour la fonction sur String: components (sharedBy: String)

dans Swift 5.1

avoir le changement pour:

string.split(separator: "/")

Gros panda
la source