Преобразовать строку 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];
}

Ответы:


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/


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()


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>

3

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

let someText = "hello"

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

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


1

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

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

extension String {
    func Letterize() -> [String] {
        return map(self) { String($0) }
    }
}

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

2
Не могли бы вы предоставить дополнительную информацию, почему это сработает? :)
пикс

1
@pix Я думаю, он хотел, чтобы это была функция, определенная в расширении String. Я добавлю это к моему ответу.
ScottyBlades

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.