Швидко натисніть на клавіші зі словника


256

Намагаючись швидко заповнити масив рядками з клавіш у словнику.

var componentArray: [String]

let dict = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("Components", ofType: "plist")!)
componentArray = dict.allKeys

Це повертає помилку: 'AnyObject', не ідентичний рядку

Також пробували

componentArray = dict.allKeys as String 

але get: "String" не можна конвертувати в [String]

Відповіді:


534

Swift 3 та Swift 4

componentArray = Array(dict.keys) // for Dictionary

componentArray = dict.allKeys // for NSDictionary

Цікаво, що у циклі for for - для імені в dict.allKeys - 'name' стає рядком і може бути надруковано та іншим чином оброблено.
green_knight

dict не має методу ключів. Це екземпляр NSDictionary, а не словник.
Уомбл

2
dict.map {$ 0.key}
Ніланшу Джайсваль

55

З Swift 3 Dictionaryмає keysвластивість. keysмає таку заяву:

var keys: LazyMapCollection<Dictionary<Key, Value>, Key> { get }

Колекція, що містить лише ключі словника.

Зверніть увагу , що LazyMapCollectionце легко можна порівнювати з Arrayз Array«S init(_:)ініціалізатор.


Від NSDictionaryдо[String]

Наступний AppDelegateфрагмент класу iOS показує, як отримати масив рядків ( [String]), використовуючи keysвластивість з NSDictionary:

введіть тут опис зображення

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    let string = Bundle.main.path(forResource: "Components", ofType: "plist")!
    if let dict = NSDictionary(contentsOfFile: string) as? [String : Int] {
        let lazyMapCollection = dict.keys
        
        let componentArray = Array(lazyMapCollection)
        print(componentArray)
        // prints: ["Car", "Boat"]
    }
    
    return true
}

Від [String: Int]до[String]

Більш загальним способом наступний код Playground показує, як отримати масив рядків ( [String]), використовуючи keysвластивість зі словника з рядковими ключами та цілими значеннями ( [String: Int]):

let dictionary = ["Gabrielle": 49, "Bree": 32, "Susan": 12, "Lynette": 7]
let lazyMapCollection = dictionary.keys

let stringArray = Array(lazyMapCollection)
print(stringArray)
// prints: ["Bree", "Susan", "Lynette", "Gabrielle"]

Від [Int: String]до[String]

У наведеному нижче коді ігрового майданчика показано, як отримати масив рядків ( [String]), використовуючи keysвластивість зі словника з цілими ключами та рядковими значеннями ( [Int: String]):

let dictionary = [49: "Gabrielle", 32: "Bree", 12: "Susan", 7: "Lynette"]
let lazyMapCollection = dictionary.keys
    
let stringArray = Array(lazyMapCollection.map { String($0) })
// let stringArray = Array(lazyMapCollection).map { String($0) } // also works
print(stringArray)
// prints: ["32", "12", "7", "49"]

дякую за деталі. У Swift 4.x тип є Dictionary<String, String>.Keys- чи є у вас розуміння, коли ми хочемо використовувати цей тип і як?
bshirley

46

Масив із клавіш словника у Swift

componentArray = [String] (dict.keys)

Я не знаю, чому люди не віддають перевагу скороченому синтаксису, тоді як це зрозуміти набагато зрозуміліше.
Наташа

9

dict.allKeysне є струною. Це [String]так, як саме вам повідомляє повідомлення про помилку (якщо, звичайно, припускати, що ключі - це всі рядки; саме це ви стверджуєте, говорячи про це).

Отже, або почніть з введення componentArrayяк [AnyObject], тому що це вводиться в API какао, або ж, якщо ви вводите dict.allKeys, киньте його [String], оскільки саме так ви ввели componentArray.


1
Це здається вже неправдою. У Swift 4.2 dict.keys (який замінює .allKeys) не є [String], це [Словник <String, Any> .Keys], і його потрібно передати перед призначенням змінної типу [String] @santo, здається, має найпростіший робочий приклад того, як це зробити.
часСміт

5
extension Array {
    public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] {
        var dict = [Key:Element]()
        for element in self {
            dict[selectKey(element)] = element
        }
        return dict
    }
}

3

NSDictionary is Class (pass by reference) Словник - це структура (pass by value ) ====== Масив з NSDictionary ======NSDictionary - клас класу Словник - це структура ключових і значущих

NSDictionary має allKeys і allValues отримують властивості з типом [Any] .NSDictionary має [Any] властивості для allkeys та allvalues

  let objesctNSDictionary = 
    NSDictionary.init(dictionary: ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"])
            let objectArrayOfAllKeys:Array = objesctNSDictionary.allKeys
            let objectArrayOfAllValues:Array = objesctNSDictionary.allValues
            print(objectArrayOfAllKeys)
            print(objectArrayOfAllValues)

====== Масив зі словника ======

Посилання Apple на властивості ключів та значень словника . введіть тут опис зображення

введіть тут опис зображення

let objectDictionary:Dictionary = 
            ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
    let objectArrayOfAllKeys:Array = Array(objectDictionary.keys)          
    let objectArrayOfAllValues:Array = Array(objectDictionary.values)
    print(objectArrayOfAllKeys)
    print(objectArrayOfAllValues)


3

З офіційної документації Array Apple :

init(_:) - Створює масив, що містить елементи послідовності.

Декларація

Array.init<S>(_ s: S) where Element == S.Element, S : Sequence

Параметри

s - Послідовність елементів, що перетворюються на масив.

Обговорення

Ви можете використовувати цей ініціалізатор для створення масиву з будь-якого іншого типу, який відповідає протоколу послідовності ... Ви також можете використовувати цей ініціалізатор для перетворення складної послідовності або типу колекції назад у масив. Наприклад, властивість ключів словника не є масивом із власним сховищем, це колекція, яка відображає його елементи зі словника лише тоді, коли до них звертаються, економлячи час та простір, необхідний для виділення масиву. Якщо вам потрібно передати ці ключі методу, який займає масив, використовуйте цей ініціалізатор для перетворення цього списку з його типу LazyMapCollection<Dictionary<String, Int>, Int> to a simple [String].

func cacheImagesWithNames(names: [String]) {
    // custom image loading and caching
 }

let namedHues: [String: Int] = ["Vermillion": 18, "Magenta": 302,
        "Gold": 50, "Cerise": 320]
let colorNames = Array(namedHues.keys)
cacheImagesWithNames(colorNames)

print(colorNames)
// Prints "["Gold", "Cerise", "Magenta", "Vermillion"]"

1

Ця відповідь буде для швидкого словника з клавішами St / String. Як ця нижче .

let dict: [String: Int] = ["hey": 1, "yo": 2, "sup": 3, "hello": 4, "whassup": 5]

Ось розширення, яке я буду використовувати.

extension Dictionary {
  func allKeys() -> [String] {
    guard self.keys.first is String else {
      debugPrint("This function will not return other hashable types. (Only strings)")
      return []
    }
    return self.flatMap { (anEntry) -> String? in
                          guard let temp = anEntry.key as? String else { return nil }
                          return temp }
  }
}

І я отримаю всі ключі пізніше, використовуючи це.

let componentsArray = dict.allKeys()


1

Ви можете використовувати dictionary.map так:

let myKeys: [String] = myDictionary.map{String($0.key) }

Пояснення: Карта повторюється через мій словник та приймає кожну пару ключів та значень як 0 доларів. Звідси ви можете отримати $ 0.key або $ 0. вартість. Всередині кінцевого закриття {} ви можете перетворити кожен елемент і повернути його. Оскільки ви хочете $ 0 і ви хочете його як рядок, то ви конвертуєте за допомогою String ($ 0.key). Ви збираєте перетворені елементи до масиву рядків.


-2
// Old version (for history)
let keys = dictionary.keys.map { $0 }
let keys = dictionary?.keys.map { $0 } ?? [T]()

// New more explained version for our ducks
extension Dictionary {

    var allKeys: [Dictionary.Key] {
        return self.keys.map { $0 }
    }
}

2
Гей, там! Хоча цей фрагмент коду може бути вирішенням, включаючи пояснення, справді допомагає покращити якість вашої публікації. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду.
Крило
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.