Перетворити рядок Swift в масив


133

Як можна перетворити рядок "Привіт" в масив ["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,  , 🐶, 🐮,  , 🇩🇪]

Тут використовуються факти, які

  • Arrayможе бути створений з 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
Чи маєте ви ідею, чому спроба приєднати let joined = ", ".join(characters);масив призводить до 'String' is not identical to 'Character'помилки?
Мохамад

3
@Mohamad: Перерахування рядка створює послідовність символів, але ", ".join(...)очікує масив рядків. Відповідь devxoul нижче показує, як ви могли розділити на масив рядків.
Мартін Р

2
@Fonix: charactersце колекція та перегляд символів рядків. Створення масиву з символів робить копію. - Звичайно, ви можете отримати доступ до персонажів безпосередньо: for i in string.characters.indices { print(string.characters[i]) }або простоfor c in string.characters { print(c) }
Martin R

2
@Fonix: ... З іншого боку, випадкове індексування рядків може бути повільним, і може бути вигідним створити масив з усіма символами один раз. Приклад: stackoverflow.com/questions/40371929/… .
Martin R

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ініціалізатор на ньому.
chrisamanse

2
@chrisamanse О, я цього не знав. Я був неправий. Дякуємо, що вказали на це. До речі, я мав намір [String]замість того, [Character]що op захотів рядковий масив :)
devxoul

22

Існує також ця корисна функція на String: компоненти (sepaBy: 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

Відповідь Мартина Р - найкращий підхід, і як він сказав, оскільки 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()
Тієм

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

1

для функції на String: компоненти (відокремленоBy: String)

у Swift 5.1

змінити:

string.split(separator: "/")

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.