Массив из словарных ключей в swift

256

Попытка заполнить массив строками из ключей в словаре в swift.

var componentArray: [String]

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

Это возвращает ошибку: «AnyObject» не идентичен строке

Также попробовал

componentArray = dict.allKeys as String 

но получите: «String» не конвертируется в [String]

Кайл Гослан
источник

Ответы:

534

Свифт 3 и Свифт 4

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

componentArray = dict.allKeys // for NSDictionary
Андрюс Степонавичюс
источник
Интересно, что в цикле for - для имени в dict.allKeys - «имя» становится строкой и может быть напечатано и обработано иным образом.
green_knight
У dict нет метода ключей. Это экземпляр NSDictionary, а не словарь.
Womble
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]

Следующий код Playground показывает, как получить массив строк ( [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"]
Imanou Petit
источник
спасибо за детали В Swift 4.x тип - есть Dictionary<String, String>.Keysли у вас понимание, когда мы хотим использовать этот тип и как?
bshirley
46

Массив из словарных ключей в Swift

componentArray = [String] (dict.keys)
Santo
источник
Я не знаю, почему люди не предпочитают сокращенный синтаксис, в то время как это намного более понятно для понимания.
Наташа
9

dict.allKeysэто не строка Это [String]именно то, о чем говорится в сообщении об ошибке (если, конечно, все ключи являются строками; это именно то, что вы утверждаете, когда говорите это).

Итак, либо начните с того, что наберите componentArrayas [AnyObject], потому что это то, как он печатается в API-интерфейсе Какао, либо, если вы разыгрываете dict.allKeys, приведите его [String], потому что это то, как вы ввели componentArray.

матовый
источник
1
Кажется, это больше не так. В Swift 4.2 dict.keys (который заменяет .allKeys) не является [String], это [Dictionary <String, Any> .Keys] и должен быть приведен перед присвоением переменной типа [String] @santo, кажется, имеет самый простой рабочий пример того, как это сделать.
TimeSmith
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 - это класс (передача по ссылке). Словарь - это структура (передача по значению ) ====== Массив из NSDictionary ======NSDictionary является типом класса Словарь - это структура ключа и значения

NSDictionary имеет allKeys, а allValues получают свойства с типом [Any] .NSDictionary имеет свойства get [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)

====== Array From Dictionary ======

Справочник 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 - последовательность элементов для превращения в массив.

обсуждение

Вы можете использовать этот инициализатор для создания массива из любого другого типа, который соответствует протоколу Sequence ... Вы также можете использовать этот инициализатор для преобразования сложной последовательности или типа коллекции обратно в массив. Например, свойство keys словаря не является массивом с собственным хранилищем, это коллекция, которая отображает свои элементы из словаря только при обращении к ним, экономя время и пространство, необходимые для выделения массива. Однако если вам нужно передать эти ключи методу, который принимает массив, используйте этот инициализатор для преобразования этого списка из его типа 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"]"
Крис Граф
источник
2

Вы можете использовать dictionary.map следующим образом:

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

Объяснение: Карта перебирает myDictionary и принимает каждую пару ключ-значение как $ 0. Отсюда вы можете получить $ 0.key или $ 0.value. Внутри замыкающего замыкания {} вы можете преобразовать каждый элемент и вернуть этот элемент. Так как вы хотите $ 0, и вы хотите его как строку, то вы конвертируете, используя String ($ 0.key). Вы собираете преобразованные элементы в массив строк.

Мео Флейта
источник
1

Этот ответ будет для быстрого словаря со строковыми ключами. Как этот ниже .

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()
jnblanchard
источник
1

Swift 5

var dict = ["key1":"Value1", "key2":"Value2"]

let k = dict.keys

var a: [String]()
a.append(contentsOf: k)

Это работает для меня.

Сиддхарт Кавтекар
источник
-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
Привет всем! Хотя этот фрагмент кода может быть решением, включение объяснения действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин, по которым вы предлагаете код.
Крыло