Wie erhalte ich den Schlüssel für einen bestimmten Index aus einem Wörterbuch in Swift?

113

Ich habe einen Dictionaryin Swift und möchte einen Schlüssel für einen bestimmten Index erhalten.

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

Ich weiß, dass ich die Schlüssel durchlaufen und protokollieren kann

for key in myDict.keys{

    NSLog("key = \(key)")

}

Seltsamerweise ist so etwas jedoch nicht möglich

var key : String = myDict.keys[0]

Warum ?

the_critic
quelle
10
Nur damit Sie wissen, ist nicht garantiert, dass Swift-Wörterbücher in einer bestimmten Reihenfolge vorliegen. Sie können also nicht sicher sein, dass die Schlüssel in der Reihenfolge indiziert werden, in der Sie sie
eingegeben haben
+1 @radex und möchte, wenn möglich, eine Quelle hinzufügen, um mehr über Ihre Aussage zu lesen.
SH

Antworten:

189

Das liegt daran, dass keysRetouren LazyMapCollection<[Key : Value], Key>, die nicht mit einem Index versehen werden können Int. Eine Möglichkeit, dies zu handhaben, besteht darin, die Wörterbücher startIndexum die Ganzzahl zu erweitern, mit der Sie einen Index erstellen möchten, zum Beispiel:

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

Eine andere mögliche Lösung wäre, ein Array mit keysals Eingabe zu initialisieren. Dann können Sie ganzzahlige Indizes für das Ergebnis verwenden:

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

Denken Sie daran, dass Wörterbücher von Natur aus ungeordnet sind. Erwarten Sie also nicht, dass der Schlüssel an einem bestimmten Index immer gleich ist.

Mick MacCallum
quelle
3
Wahrscheinlich schneller wäre es, Array(myDict)[0].0da es das Schlüsselarray nicht kopieren würde und die internen Strukturen des Wörterbuchs nicht kopieren sollte, obwohl dies möglich wäre.
David Berry
5
Beachten Sie, dass es kein Versprechen darüber gibt, welcher Schlüssel zurückgegeben wird, aber eine gute Anmerkung zum zurückgegebenen "Ansicht" -Typ. Meine Antwort wurde gelöscht, da sie für die Frage nicht zutraf.
Rob Napier
8
Um zu verdeutlichen, was Rob sagt, obwohl es so aussieht, als würden die Schlüssel jedes Mal gleich bestellt, ist dies nicht der Fall und lediglich ein Implementierungsdetail. Es ist sehr wahrscheinlich, dass Sie den Schlüssel "foo" hinzufügen und die interne Darstellung das Wörterbuch vollständig neu ordnet. Ein Wörterbuch ist eine ungeordnete Sammlung von Schlüssel-Wert-Paaren. Daher werden in der obigen Antwort gefährliche Annahmen getroffen, die nicht zutreffen.
Jack Lawrence
8
Wenn Sie die Schlüssel in einer bestimmten Reihenfolge benötigen, bewahren Sie ein Array davon auf. Dann können Sie sie wie verwenden myDict[keysArray[0]].
Zev Eisenberg
1
Funktioniert nicht ...'NSDictionary' is not convertible to '_ArrayBuffer<T>'
Chris
53

Swift 3: Array()kann dazu nützlich sein.

Schlüssel abrufen:

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

Wert erhalten :

Array(myDict)[index].value
Roy
quelle
Dies funktioniert für mich für Swift 3. Ich verstehe jedoch nicht, warum das erstellte Array neu angeordnet wurde. Irgendwelche Gedanken?
Slarty Bartfast
Danke, das hat mir geholfen
ANE
1
@ Josef Was ist damit kontraintuitiv? Wörterbücher sind Schlüssel-Wert-Paare, sodass die Idee eines Index nicht behoben werden kann. Auf Arrays wird über den Index zugegriffen, sodass ein Wörterbuch in ein Array umgewandelt wird und dann über den Index auf das Array zugegriffen wird. Ein Wörterbuch wie ["a": 1, "b": 2]kann in ein Array von Wörterbüchern umgewandelt werden [[key: "a", value: 1], [key: "b", value: 2]], auf die dann über den Index zugegriffen werden kann.
Peter R
29

Hier ist eine kleine Erweiterung für den Zugriff auf Schlüssel und Werte im Wörterbuch nach Index:

extension Dictionary {
    subscript(i: Int) -> (key: Key, value: Value) {
        return self[index(startIndex, offsetBy: i)]
    }
}
bzz
quelle
3
'Voraus'-API wurde in Swift 2.0 entfernt - self [self.startIndex.advancedBy (i)] -
Romain
2
@ TomSawyer-Wörterbücher werden nicht bestellt.
Jose Ramirez
12

Sie können ein Wörterbuch durchlaufen und einen Index mit for-in und enumerate abrufen (wie andere gesagt haben, gibt es keine Garantie dafür, dass es wie unten beschrieben bestellt wird).

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

Wenn Sie zuerst sortieren möchten ..

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)]

dann iterieren.

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

Wenn Sie ein geordnetes Wörterbuch erstellen möchten, sollten Sie sich Generics ansehen.

Matthew Korporaal
quelle
1
Was wäre, wenn ich nach dem Index für 456 suchen wollte?
Famic Tech
2
@ Max, das ist alte Swift-Syntax. Jetzt können Sie verwenden: dict.enumerated().forEach { (index, element) in ... }
Matthew Korporaal
8

Unter https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/CollectionTypes.html :

Wenn Sie die Schlüssel oder Werte eines Wörterbuchs mit einer API verwenden müssen, die eine Array-Instanz verwendet, initialisieren Sie ein neues Array mit der Eigenschaft keys oder values:

let airportCodes = [String](airports.keys) // airportCodes is ["TYO", "LHR"]   
let airportNames = [String](airports.values) // airportNames is ["Tokyo", "London Heathrow"]
Jack
quelle
5

SWIFT 3. Beispiel für das erste Element

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

if let firstLang = wordByLanguage.first?.key {
    print(firstLang)  // English
}
Włodzimierz Woźniak
quelle
3
Was wäre, wenn ich den Index erhalten wollte, in dem der Schlüssel polnisch ist?
Famic Tech
5

In Swift 3 versuchen , diesen Code zu verwenden Key-Wert - Paar (Tupel) an bestimmten Index zu erhalten:

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

Hier ist ein Beispiel mit 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
Sean Chen
quelle
3

SWIFT 4


Etwas abseits des Themas: Aber hier ist, wenn Sie ein Array von Wörterbüchern haben, d. H. [[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
Suhaib
quelle
1
Wie kann ich den Index des Elements mit dem Alter = xxxx in Ihrem Beispiel abrufen?
Famic Tech
1
arrayIndex = 0, ageDictIndex = 1, Array (array_has_dictionary [arrayIndex] .keys) [ageDictIndex] = xxxx
Kristian
@FamicTech, Kris beantwortete Ihre Frage
Suhaib
0

Ich suchte nach so etwas wie einer LinkedHashMap in Java. Weder Swift noch Objective-C haben eine, wenn ich mich nicht irre.

Mein erster Gedanke war, mein Wörterbuch in ein Array zu packen. [[String: UIImage]]aber dann wurde mir klar, dass es verrückt war, den Schlüssel aus dem Wörterbuch zu holen, Array(dict)[index].keyalso ging ich mit Tuples. Jetzt sieht mein Array so aus, [(String, UIImage)]dass ich es abrufen kann tuple.0. Keine Konvertierung mehr in ein Array. Nur meine 2 Cent.

newDeveloper
quelle