Matriz de teclas de diccionario en swift

256

Intentando llenar una matriz con cadenas de las teclas en un diccionario en forma rápida.

var componentArray: [String]

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

Esto devuelve un error de: 'AnyObject' no idéntico a la cadena

También probé

componentArray = dict.allKeys as String 

pero obtener: 'String' no es convertible a [String]

Kyle Goslan
fuente

Respuestas:

534

Swift 3 y Swift 4

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

componentArray = dict.allKeys // for NSDictionary
Andrius Steponavičius
fuente
Curiosamente, en un bucle for - for name en dict.allKeys - 'name' se convierte en una cadena y puede imprimirse y procesarse de otra manera.
green_knight
dict no tiene un método de claves. Es una instancia de NSDictionary, no un diccionario.
Womble
2
dict.map {$ 0.key}
Nilanshu Jaiswal
55

Con Swift 3, Dictionarytiene una keyspropiedad. keystiene la siguiente declaración:

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

Una colección que contiene solo las claves del diccionario.

Tenga en cuenta que LazyMapCollectiontan fácilmente se puede asignar a una Arraycon Array's init(_:)inicializador.


De NSDictionarya[String]

El siguiente AppDelegatefragmento de clase de iOS muestra cómo obtener una matriz de cadenas ( [String]) usando la keyspropiedad de a NSDictionary:

ingrese la descripción de la imagen aquí

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
}

De [String: Int]a[String]

De manera más general, el siguiente código de Playground muestra cómo obtener una matriz de cadenas ( [String]) usando la keyspropiedad de un diccionario con claves de cadena y valores enteros ( [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"]

De [Int: String]a[String]

El siguiente código de Playground muestra cómo obtener una matriz de cadenas ( [String]) usando la keyspropiedad de un diccionario con claves enteras y valores de cadena ( [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
fuente
Gracias por el detalle. En Swift 4.x, el tipo es Dictionary<String, String>.Keys: ¿tiene alguna idea de cuándo queremos usar ese tipo y cómo?
bshirley
46

Matriz de teclas de diccionario en Swift

componentArray = [String] (dict.keys)
Santo
fuente
No sé por qué las personas no prefieren la sintaxis abreviada mientras es mucho más claro de entender.
Natasha
9

dict.allKeysNo es una cadena. Es [String]exactamente lo que le dice el mensaje de error (suponiendo, por supuesto, que las claves son todas cadenas; esto es exactamente lo que está afirmando cuando dice eso).

Por lo tanto, comience escribiendo componentArraycomo [AnyObject], porque así es como se escribe en la API de Cocoa, o bien, si lanza dict.allKeys, envíe a [String], porque así es como ha escrito componentArray.

mate
fuente
1
Esto ya no parece cierto. En Swift 4.2 dict.keys (que reemplaza a .allKeys) no es una [String], es un [Dictionary <String, Any> .Keys] y debe emitirse antes de asignar a una variable de tipo [String] @santo parece tener El ejemplo de trabajo más simple de cómo hacerlo.
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
    }
}
Jitesh Desai
fuente
3

NSDictionary es Clase (pase por referencia) Diccionario es Estructura (pase por valor ) ====== Matriz de NSDictionary ======NSDictionary es tipo de clase El diccionario es una estructura de clave y valor

NSDictionary tiene allKeys y allValues obtiene propiedades con el tipo [Any] .NSDictionary tiene propiedades [Any] para allkeys y 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)

====== Matriz del diccionario ======

Referencia de Apple para las propiedades de valores y claves del Diccionario . ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

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)
Darshan Panchal
fuente
3

De la documentación oficial de Array Apple :

init(_:) - Crea una matriz que contiene los elementos de una secuencia.

Declaración

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

Parámetros

s - La secuencia de elementos para convertir en una matriz.

Discusión

Puede usar este inicializador para crear una matriz a partir de cualquier otro tipo que se ajuste al protocolo de secuencia ... También puede usar este inicializador para convertir una secuencia compleja o un tipo de colección a una matriz. Por ejemplo, la propiedad de claves de un diccionario no es una matriz con su propio almacenamiento, es una colección que asigna sus elementos del diccionario solo cuando se accede a ellos, ahorrando el tiempo y el espacio necesarios para asignar una matriz. Sin embargo, si necesita pasar esas claves a un método que toma una matriz, use este inicializador para convertir esa lista de su tipo de 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"]"
Chris Graf
fuente
2

Puede usar dictionary.map así:

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

La explicación: Map itera a través de myDictionary y acepta cada par de clave y valor como $ 0. Desde aquí puede obtener $ 0.key o $ 0.value. Dentro del cierre final {}, puede transformar cada elemento y devolver ese elemento. Como quieres $ 0 y lo quieres como una cadena, entonces conviertes usando String ($ 0.key). Recopila los elementos transformados en una serie de cadenas.

Flauta Meo
fuente
1

Esta respuesta será para un diccionario rápido con teclas de cadena. Como este a continuación .

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

Aquí está la extensión que usaré.

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 }
  }
}

Y obtendré todas las claves más tarde usando esto.

let componentsArray = dict.allKeys()
jnblanchard
fuente
1

Swift 5

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

let k = dict.keys

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

Esto funciona para mi.

Siddharth Kavthekar
fuente
-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 }
    }
}
Igor Bachek
fuente
2
¡Hola! Si bien este fragmento de código puede ser la solución, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no saber los motivos de su sugerencia de código.
Ala