Преобразовать строку Swift в массив

133

Как я могу преобразовать строку «Hello» в массив [«H», «e», «l», «l», «o»] в Swift?

В Objective-C я использовал это:

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
источник

Ответы:

339

В Swift это еще проще:

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

Здесь используются факты, которые

  • an Arrayможет быть создан из a SequenceType, и
  • Stringсоответствует SequenceTypeпротоколу, а его генератор последовательности перечисляет символы.

А поскольку строки Swift полностью поддерживают Unicode, это работает даже с символами за пределами «базовой многоязычной плоскости» (такими как) и с расширенными кластерами графем (такими как 🇩🇪, который фактически состоит из двух скаляров Unicode).


Обновление: Начиная с Swift 2, String больше не соответствует SequenceType, но charactersсвойство предоставляет последовательность символов Unicode:

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

Это также работает в Swift 3 .


Обновление: Начиная с Swift 4, String это (снова) набор его Characters:

let string = "Hello 🐶🐮 🇩🇪"
let characters = Array(string)
print(characters)
// ["H", "e", "l", "l", "o", " ", "🐶", "🐮", " ", "🇩🇪"]
Мартин Р
источник
1
Вы хоть представляете, почему попытка join ( let joined = ", ".join(characters);) массив приводит к 'String' is not identical to 'Character'ошибке?
Mohamad
3
@Mohamad: перечисление строки производит последовательность символов, но ", ".join(...)ожидает массив строк. Ответ devxoul ниже показывает, как можно разбить на массив строк.
Martin R
2
@Fonix: charactersэто коллекция и представление о строковых символах. Создание массива из символов делает копию. - Конечно, можно получить доступ к персонажам напрямую: for i in string.characters.indices { print(string.characters[i]) }или простоfor c in string.characters { print(c) }
Мартин Р
2
@Fonix: ... С другой стороны, случайное индексирование в строки может быть медленным, и может быть полезно создать массив со всеми символами один раз. Пример: stackoverflow.com/questions/40371929/… .
Мартин Р
2
@DaniSpringer: Swift 4 в настоящее время находится в бета-версии, вам понадобится бета-версия Xcode 9: developer.apple.com/swift/resources .
Мартин Р
102

Редактировать (Swift 4)

В Swift 4 вам не нужно использовать charactersдля использования map(). Просто делай map()на String.

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

Или, если вы предпочитаете короче: "ABC".map(String.init) (2 байта 😀)

Редактировать (Swift 2 и Swift 3)

В Swift 2 и Swift 3 вы можете использовать map()функцию для charactersсвойства.

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

Оригинал (Swift 1.x)

Принятый ответ не кажется лучшим, потому что преобразованная последовательность - Stringэто не Stringпоследовательность, а Character:

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

Это ниже работает для меня:

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

Ссылка на глобальную функцию map()находится здесь: http://swifter.natecook.com/func/map/

devxoul
источник
12
Немного короче:arr = map(str) { String($0) }
Мартин Р
1
ArrayВместо этого используйте инициализатор:Array("ABC".characters)
chrisamanse
1
@ chrisamanse, нет разницы между "ABC".charactersи Array("ABC".characters).
devxoul
2
В Swift 3 все по-другому. "ABC".charactersВозвращает тип String.CharacterView. Чтобы преобразовать его в массив, в частности типа [Character], вам нужно будет использовать для него Arrayинициализатор.
Крисаманс
2
@chrisamanse О, я этого не знал. Я ошибался. Спасибо за указание на это. Кстати, я намеревался, [String]а не [Character]потому, что оператору нужен строковый массив :)
devxoul
22

Также есть эта полезная функция для String: components (separatedBy: String)

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

Хорошо работает со строками, разделенными символом типа ";" или даже "\ n"

Фредерик Адда
источник
8

Обновлено для Swift 4

Вот 3 способа.

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

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

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

В некоторых случаях люди действительно хотят преобразовать строку в массив маленьких строк длиной 1 символ каждая. Вот супер эффективный способ сделать это:

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

Свифт 3

Вот 3 способа.

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

В некоторых случаях люди действительно хотят преобразовать строку в массив маленьких строк длиной 1 символ каждая. Вот супер эффективный способ сделать это:

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

Или вы можете добавить расширение для String.

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

Тогда вы можете назвать это так:

let charArr = "Cat".letterize()
ScottyBlades
источник
4
    let string = "hell0"
    let ar = Array(string.characters)
    print(ar)
Уильям Ху
источник
В отношении этой проблемы не было изменений между Swift 2 и 3. Это решение идентично версии Swift 2 в stackoverflow.com/a/25921323/1187415 .
Martin R
3

Ответ Martin R - лучший подход, и, как он сказал, поскольку String соответствует протоколу SquenceType, вы также можете перечислять строку, получая каждый символ на каждой итерации.

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

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

println(charactersArray)
Альберто Баррера
источник
2
Или просто for character in characters { charactersArray.append(character)}безenumeration()
Tieme
3

В Swift 4, как Stringи в коллекции Character, вам нужно использоватьmap

let array1 = Array("hello") // Array<Character>
let array2 = Array("hello").map({ "\($0)" }) // Array<String>
let array3 = "hello".map(String.init) // Array<String>
onmyway133
источник
3

Легкий способ сделать это - обратиться mapк переменной и вернуть каждую Characterкак String:

let someText = "hello"

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

Выход должен быть ["h", "e", "l", "l", "o"].

atolite
источник
1

Вы также можете создать расширение:

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

extension String {
    func Letterize() -> [String] {
        return map(self) { String($0) }
    }
}
fabrizioM
источник
1
func letterize() -> [Character] {
    return Array(self.characters)
}
Петр Пщулковский
источник
2
Не могли бы вы предоставить дополнительную информацию, почему это сработает? :)
пикс
1
@pix Я думаю, он хотел, чтобы это была функция, определенная в расширении String. Я добавлю это к моему ответу.
ScottyBlades
1

для функции на строке: компоненты (separaBy: строка)

в Swift 5.1

изменить на:

string.split(separator: "/")

Толстая панда
источник