Come ottengo la chiave in un indice specifico da un dizionario in Swift?


114

Ho un Dictionaryin Swift e vorrei ottenere una chiave in un indice specifico.

var myDict : Dictionary<String,MyClass> = Dictionary<String,MyClass>()

So di poter scorrere le chiavi e registrarle

for key in myDict.keys{

    NSLog("key = \(key)")

}

Tuttavia, abbastanza stranamente, qualcosa del genere non è possibile

var key : String = myDict.keys[0]

Perché ?


11
Tieni presente che non è garantito che i dizionari Swift siano in un ordine specifico. Quindi non puoi aspettarti con certezza che le chiavi vengano indicizzate nell'ordine in cui le hai inserite.
radex

+1 @radex e vorrei anche aggiungere, se possibile, una fonte per leggere di più sulla tua dichiarazione sarebbe molto apprezzato.
SH

Risposte:


191

Questo perché keysritorna LazyMapCollection<[Key : Value], Key>, che non può essere sottoscritto con un Int. Un modo per gestirlo è far avanzare il dizionario del startIndexnumero intero che si desidera inserire, ad esempio:

let intIndex = 1 // where intIndex < myDictionary.count
let index = myDictionary.index(myDictionary.startIndex, offsetBy: intIndex)
myDictionary.keys[index]

Un'altra possibile soluzione sarebbe inizializzare un array con keyscome input, quindi puoi usare indici interi sul risultato:

let firstKey = Array(myDictionary.keys)[0] // or .first

Ricorda, i dizionari sono intrinsecamente non ordinati, quindi non aspettarti che la chiave in un dato indice sia sempre la stessa.


3
Probabilmente sarebbe più veloce Array(myDict)[0].0poiché non copia l'array di chiavi e non dovrebbe copiare le strutture interne del dizionario, anche se potrebbe.
David Berry

5
Tieni presente che non ci sono promesse su quale chiave verrà restituita, ma una buona nota sul tipo di "visualizzazione" che viene restituito. Ho cancellato la mia risposta poiché non si applicava effettivamente alla domanda.
Rob Napier

9
Per chiarire ciò che sta dicendo Rob, anche se può sembrare che le chiavi siano sempre ordinate ogni volta allo stesso modo, non è così ed è semplicemente un dettaglio di implementazione. È molto probabile che tu possa aggiungere la chiave "foo" e la rappresentazione interna riordinerà completamente il dizionario. Un dizionario è una raccolta non ordinata di coppie chiave-valore. Pertanto, la risposta di cui sopra sta facendo ipotesi pericolose che non sono vere.
Jack Lawrence

8
Se hai bisogno delle chiavi in ​​un ordine specifico, tienine un array. Quindi puoi usarli come myDict[keysArray[0]].
Zev Eisenberg

1
Non funziona ...'NSDictionary' is not convertible to '_ArrayBuffer<T>'
Chris

53

Swift 3: Array()può essere utile per farlo.

Ottieni chiave:

let index = 5 // Int Value
Array(myDict)[index].key

Ottieni valore:

Array(myDict)[index].value

Questo funziona per Swift 3. Non capisco perché l'array creato sia stato riorganizzato. qualche idea?
Slarty Bartfast

Grazie, questo mi ha aiutato
ANE

1
@ josef Che cosa è contro intuitivo? I dizionari sono coppie chiave e valore, quindi l'idea di un indice non si risolve. Gli array sono accessibili tramite indice, quindi questo trasforma un dizionario IN un array e quindi accede all'array tramite il suo indice. Un dizionario come ["a": 1, "b": 2], può essere trasformato in un array di dizionari come [[key: "a", value: 1], [key: "b", value: 2]], a questo si può accedere tramite indice.
Peter R

29

Ecco una piccola estensione per accedere a chiavi e valori nel dizionario in base all'indice:

extension Dictionary {
    subscript(i: Int) -> (key: Key, value: Value) {
        return self[index(startIndex, offsetBy: i)]
    }
}

3
L'API "advance" è stata rimossa nell'uso di Swift 2.0 - self [self.startIndex.advancedBy (i)] -
Romain

2
I dizionari @TomSawyer non sono ordinati.
Jose Ramirez

12

Puoi iterare su un dizionario e prendere un indice con for-in ed enumerare (come altri hanno detto, non c'è garanzia che uscirà ordinato come sotto)

let dict = ["c": 123, "d": 045, "a": 456]

for (index, entry) in enumerate(dict) {
    println(index)   // 0       1        2
    println(entry)   // (d, 45) (c, 123) (a, 456)
}

Se vuoi ordinare prima ..

var sortedKeysArray = sorted(dict) { $0.0 < $1.0 }
println(sortedKeysArray)   // [(a, 456), (c, 123), (d, 45)]

var sortedValuesArray = sorted(dict) { $0.1 < $1.1 }
println(sortedValuesArray) // [(d, 45), (c, 123), (a, 456)]

quindi iterare.

for (index, entry) in enumerate(sortedKeysArray) {
    println(index)    // 0   1   2
    println(entry.0)  // a   c   d
    println(entry.1)  // 456 123 45
}

Se vuoi creare un dizionario ordinato, dovresti guardare in Generics.


1
e se volessi cercare quello che l'indice era uguale a 456?
Famic Tech

2
@ Max, questa è la vecchia sintassi di Swift. Ora puoi usare: dict.enumerated().forEach { (index, element) in ... }
Matthew Korporaal


5

SWIFT 3. Esempio per il primo elemento

let wordByLanguage = ["English": 5, "Spanish": 4, "Polish": 3, "Arabic": 2]

if let firstLang = wordByLanguage.first?.key {
    print(firstLang)  // English
}

3
E se volessi ottenere l'indice in cui la chiave è il polacco?
Famic Tech

5

In Swift 3 prova a utilizzare questo codice per ottenere la coppia chiave-valore (tupla) a un dato indice:

extension Dictionary {
    subscript(i:Int) -> (key:Key,value:Value) {
        get {
            return self[index(startIndex, offsetBy: i)];
        }
    }
}

3

Ecco un esempio, utilizzando Swift 1.2

var person = ["name":"Sean", "gender":"male"]
person.keys.array[1] // "gender", get a dictionary key at specific index 
person.values.array[1] // "male", get a dictionary value at specific index

3

SWIFT 4


Leggermente fuori tema: ma qui è se hai un array di dizionari, ad esempio: [[String: String]]

var array_has_dictionary = [ // Start of array

   // Dictionary 1

   [ 
     "name" : "xxxx",
     "age" : "xxxx",
     "last_name":"xxx"
   ],

   // Dictionary 2

   [ 
     "name" : "yyy",
     "age" : "yyy",
     "last_name":"yyy"
   ],

 ] // end of array


cell.textLabel?.text =  Array(array_has_dictionary[1])[1].key
// Output: age -> yyy

1
Come posso ottenere l'indice dell'articolo che ha age = xxxx nel tuo esempio?
Famic Tech

1
arrayIndex = 0, ageDictIndex = 1, Array (array_has_dictionary [arrayIndex] .keys) [ageDictIndex] = xxxx
Kristian

@FamicTech, Kris ha risposto alla tua domanda
Suhaib

0

Stavo cercando qualcosa come LinkedHashMap in Java. Né Swift né Objective-C ne hanno uno se non mi sbaglio.

Il mio pensiero iniziale è stato quello di racchiudere il mio dizionario in un array. [[String: UIImage]]ma poi mi sono reso conto che prendere la chiave dal dizionario era stravagante, Array(dict)[index].keyquindi sono andato con le tuple. Ora il mio array sembra [(String, UIImage)]così posso recuperarlo da tuple.0. Non è più necessario convertirlo in un array. Solo i miei 2 centesimi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.