Converter string Swift em array

133

Como posso converter uma string "Hello" em uma matriz ["H", "e", "l", "l", "o"] no Swift?

No Objective-C, usei isso:

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
fonte

Respostas:

339

É ainda mais fácil no Swift:

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

Isso usa os fatos que

  • um Arraypode ser criado a partir de SequenceTypee
  • Stringestá em conformidade com o SequenceTypeprotocolo e seu gerador de seqüências enumera os caracteres.

E como as strings Swift têm suporte total para Unicode, isso funciona mesmo com caracteres fora do "Plano multilíngue básico" (como 🐶) e com clusters de grafema estendidos (como 🇩🇪, que na verdade é composto por dois escalares Unicode).


Atualização: A partir do Swift 2, String não está mais em conformidade SequenceType, mas a characterspropriedade fornece uma sequência dos caracteres Unicode:

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

Isso funciona no Swift 3 também.


Atualização: A partir do Swift 4, String é (novamente) uma coleção de seus Characters:

let string = "Hello 🐶🐮 🇩🇪"
let characters = Array(string)
print(characters)
// ["H", "e", "l", "l", "o", " ", "🐶", "🐮", " ", "🇩🇪"]
Martin R
fonte
1
Você tem alguma idéia de por que tentar juntar ( let joined = ", ".join(characters);) a matriz resulta em um 'String' is not identical to 'Character'erro?
Mohamad
3
@ Mohamad: Enumerar uma string produz uma sequência de caracteres, mas ", ".join(...)espera uma matriz de strings. A resposta do devxoul abaixo mostra como você pode se dividir em uma série de strings.
Martin R
2
@Fonix: charactersé uma coleção e uma visão sobre os caracteres das strings. Criar uma matriz a partir dos caracteres faz uma cópia. - Claro que pode acessar os personagens diretamente: for i in string.characters.indices { print(string.characters[i]) }ou apenasfor c in string.characters { print(c) }
Martin R
2
@Fonix: ... Por outro lado, a indexação aleatória em strings pode ser lenta e pode ser vantajoso criar uma matriz com todos os caracteres uma vez. Exemplo: stackoverflow.com/questions/40371929/… .
Martin R
2
@DaniSpringer: O Swift 4 está atualmente na versão beta, você precisará do Xcode 9 beta: developer.apple.com/swift/resources .
Martin R
102

Editar (Swift 4)

No Swift 4, você não precisa charactersusar map(). Basta fazer map()em String.

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

Ou se você preferir mais curto: "ABC".map(String.init)(2 bytes 😀)

Editar (Swift 2 e Swift 3)

No Swift 2 e Swift 3, você pode usar a map()função para characterspropriedade.

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

Original (Swift 1.x)

A resposta aceita não parece ser a melhor, porque a sequência convertida Stringnão é uma Stringsequência, mas Character:

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

Isso abaixo funciona para mim:

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

A referência para uma função global map()está aqui: http://swifter.natecook.com/func/map/

devxoul
fonte
12
Um pouco mais curto:arr = map(str) { String($0) }
Martin R
1
Use o Arrayinicializador:Array("ABC".characters)
chrisamanse 30/09/16
1
@chrisamanse, Não há diferença entre "ABC".characterse Array("ABC".characters).
Devxoul # 30/16
2
É diferente no Swift 3. "ABC".charactersretorna um tipo String.CharacterView. Para convertê-lo em uma matriz, especificamente do tipo [Character], você precisaria usar o Arrayinicializador.
Chrisamanse #
2
@chrisamanse Oh, eu não sabia disso. Eu estava errado. Obrigado por apontar isso. By the way, eu pretendia [String], em vez de [Character]por causa op queria uma matriz de cadeia :)
devxoul
22

Há também essa função útil em String: components (protectedBy: String)

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

Funciona bem para lidar com seqüências de caracteres separadas por um caractere como ";" ou até "\ n"

Frédéric Adda
fonte
8

Atualizado para o Swift 4

Aqui estão três maneiras.

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

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

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

Em alguns casos, o que as pessoas realmente querem é uma maneira de converter uma string em uma série de pequenas strings com 1 caractere cada. Aqui está uma maneira super eficiente de fazer isso:

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

Swift 3

Aqui estão três maneiras.

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

Em alguns casos, o que as pessoas realmente querem é uma maneira de converter uma string em uma série de pequenas strings com 1 caractere cada. Aqui está uma maneira super eficiente de fazer isso:

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

Ou você pode adicionar uma extensão a String.

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

Então você pode chamar assim:

let charArr = "Cat".letterize()
ScottyBlades
fonte
4
    let string = "hell0"
    let ar = Array(string.characters)
    print(ar)
William Hu
fonte
Não houve alterações entre o Swift 2 e o 3 com relação a esse problema. Esta solução é idêntica à versão Swift 2 em stackoverflow.com/a/25921323/1187415 .
Martin R
3

A resposta de Martin R é a melhor abordagem e, como ele disse, porque String está em conformidade com o protocolo SquenceType, você também pode enumerar uma string, obtendo cada caractere em cada iteração.

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
fonte
2
Ou apenas for character in characters { charactersArray.append(character)}sem oenumeration()
Tieme 14/11/14
3

No Swift 4, como Stringé uma coleção de Character, você precisa usarmap

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

Uma maneira fácil de fazer isso é mapa variável e retornar cada Characteruma como String:

let someText = "hello"

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

A saída deve ser ["h", "e", "l", "l", "o"].

atolito
fonte
1

Você também pode criar uma extensão:

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

extension String {
    func Letterize() -> [String] {
        return map(self) { String($0) }
    }
}
fabrizioM
fonte
1
func letterize() -> [Character] {
    return Array(self.characters)
}
Piotr Pszczółkowski
fonte
2
Você pode fornecer mais informações sobre por que isso funcionará? :)
pix 27/10
1
@pix Eu acho que ele quis que isso fosse uma função definida em uma extensão de String. Vou acrescentar isso à minha resposta.
precisa saber é o seguinte
1

para a função em String: components (selectedBy: String)

no Swift 5.1

altere para:

string.split(separator: "/")

Panda gordo
fonte