Bagaimana cara mendapatkan kunci pada indeks tertentu dari Kamus di Swift?

114

Saya memiliki Dictionarydi Swift dan saya ingin mendapatkan kunci pada indeks tertentu.

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

Saya tahu bahwa saya dapat mengulang kunci dan mencatatnya

for key in myDict.keys{

    NSLog("key = \(key)")

}

Namun, anehnya, hal seperti ini tidak mungkin dilakukan

var key : String = myDict.keys[0]

Kenapa?

the_critic
sumber
11
Sekadar info, kamus Swift tidak dijamin memiliki urutan tertentu. Jadi, Anda tidak dapat berharap secara pasti bahwa kunci akan diindeks dalam urutan yang Anda masukkan.
radex
Memberi +1 pada @radex dan juga ingin menambahkan, jika memungkinkan, sumber untuk membaca lebih lanjut tentang pernyataan Anda akan sangat dihargai.
SH

Jawaban:

191

Itu karena keyspengembalian LazyMapCollection<[Key : Value], Key>, yang tidak bisa dilanggan dengan Int. Salah satu cara untuk mengatasinya adalah dengan memajukan kamus startIndexdengan bilangan bulat yang ingin Anda gunakan untuk subskrip, misalnya:

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

Solusi lain yang mungkin adalah menginisialisasi array dengan keyssebagai input, kemudian Anda dapat menggunakan subskrip integer pada hasilnya:

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

Ingat, kamus pada dasarnya tidak berurutan, jadi jangan berharap kunci pada indeks tertentu selalu sama.

Mick MacCallum
sumber
3
Mungkin lebih cepat Array(myDict)[0].0karena tidak akan menyalin larik kunci, dan seharusnya tidak menyalin struktur internal kamus, meskipun mungkin.
David Berry
5
Perlu diingat bahwa tidak ada janji tentang kunci mana yang akan dikembalikan, tetapi catatan yang baik tentang jenis "tampilan" yang dikembalikan. Menghapus jawaban saya karena tidak benar-benar sesuai dengan pertanyaan.
Rob Napier
9
Untuk memperjelas apa yang dikatakan Rob, meskipun sepertinya kunci selalu diurutkan dengan sama setiap saat, ini bukan masalahnya dan hanyalah detail implementasi. Sangat mungkin bahwa Anda dapat menambahkan kunci "foo" dan representasi internal akan sepenuhnya menyusun ulang kamus. Dictionary adalah kumpulan key-value pair yang tidak berurutan . Oleh karena itu, jawaban di atas adalah membuat asumsi berbahaya yang tidak benar.
Jack Lawrence
8
Jika Anda membutuhkan kunci dalam urutan tertentu, pertahankan susunannya. Kemudian Anda bisa menggunakannya seperti myDict[keysArray[0]].
Zev Eisenberg
1
Tidak bekerja ...'NSDictionary' is not convertible to '_ArrayBuffer<T>'
Chris
53

Swift 3: Array()dapat berguna untuk melakukan ini.

Dapatkan Kunci:

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

Dapatkan Nilai:

Array(myDict)[index].value
roy
sumber
Ini bekerja untuk saya untuk Swift 3. Namun, tidak mengerti mengapa Array yang dibuat diatur ulang. Ada pemikiran?
Slarty Bartfast
Terima kasih ini membantu saya
ANE
1
@josef Bagaimana dengan counter intuitif? Kamus adalah pasangan kunci, nilai, jadi gagasan tentang indeks tidak dapat diperbaiki. Array diakses oleh indeks, jadi ini mengubah kamus MENJADI Array, dan kemudian mengakses array dengan indeksnya. Sebuah kamus seperti ["a": 1, "b": 2], dapat diubah menjadi sebuah susunan kamus seperti [[key: "a", value: 1], [key: "b", value: 2]], ini kemudian dapat diakses oleh indeks.
Peter R
29

Berikut adalah ekstensi kecil untuk mengakses kunci dan nilai dalam kamus dengan indeks:

extension Dictionary {
    subscript(i: Int) -> (key: Key, value: Value) {
        return self[index(startIndex, offsetBy: i)]
    }
}
bzz
sumber
3
API 'advance' telah dihapus dalam penggunaan Swift 2.0 - self [self.startIndex.advancedBy (i)] -
Romain
2
Kamus @TomSawyer tidak dipesan.
Jose Ramirez
12

Anda dapat mengulangi kamus dan mengambil indeks dengan for-in dan enumerate (seperti yang dikatakan orang lain, tidak ada jaminan itu akan keluar dengan urutan seperti di bawah)

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

Jika Anda ingin menyortir dulu ..

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

lalu lakukan iterasi.

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

Jika Anda ingin membuat kamus berurutan, Anda harus melihat ke Generik.

Matthew Korporaal
sumber
1
bagaimana jika saya ingin mencari apa indeks itu sama dengan 456?
Famic Tech
2
@ Max, ini adalah sintaks Swift lama. Sekarang Anda dapat menggunakan: dict.enumerated().forEach { (index, element) in ... }
Matthew Korporaal
5

SWIFT 3. Contoh elemen pertama

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

if let firstLang = wordByLanguage.first?.key {
    print(firstLang)  // English
}
Włodzimierz Woźniak
sumber
3
Bagaimana jika saya ingin mendapatkan indeks di mana kuncinya adalah Polandia?
Famic Tech
5

Di Swift 3 coba gunakan kode ini untuk mendapatkan Key-Value Pair (tuple) pada indeks yang diberikan:

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

Berikut ini contohnya, menggunakan 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
sumber
3

SWIFT 4


Agak di luar topik: Tapi di sini jika Anda memiliki Array Kamus, misalnya : [[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
sumber
1
Bagaimana saya bisa mendapatkan indeks item yang memiliki age = xxxx dalam contoh Anda?
Famic Tech
1
arrayIndex = 0, ageDictIndex = 1, Array (array_has_dictionary [arrayIndex] .keys) [ageDictIndex] = xxxx
Kristian
@FamicTech, Kris menjawab pertanyaan Anda
Suhaib
0

Saya mencari sesuatu seperti LinkedHashMap di Java. Baik Swift maupun Objective-C tidak memilikinya jika saya tidak salah.

Pikiran awal saya adalah membungkus kamus saya dalam Array. [[String: UIImage]]tapi kemudian saya menyadari bahwa mengambil kunci dari kamus itu aneh Array(dict)[index].keyjadi saya pergi dengan Tuple. Sekarang array saya terlihat seperti [(String, UIImage)]sehingga saya dapat mengambilnya kembali tuple.0. Tidak ada lagi mengubahnya menjadi Array. Hanya 2 sen saya.

newDeveloper
sumber