Swift'deki bir Sözlükten belirli bir dizindeki anahtarı nasıl edinebilirim?


114

DictionarySwift in a sahibim ve belirli bir dizinde bir anahtar almak istiyorum.

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

Anahtarları yineleyip günlüğe kaydedebileceğimi biliyorum

for key in myDict.keys{

    NSLog("key = \(key)")

}

Ancak, garip bir şekilde, böyle bir şey mümkün değil

var key : String = myDict.keys[0]

Neden ?


11
Bildiğiniz gibi, Swift sözlüklerinin belirli bir sırada olması garanti edilmez. Dolayısıyla, anahtarların onları koyduğunuz sırayla dizine
eklenmesini bekleyemezsiniz

+1 @radex ve ayrıca mümkünse ifadeniz hakkında daha fazla bilgi okuyabileceğiniz bir kaynak eklemek isterim.
SH

Yanıtlar:


191

Bunun nedeni bulunuyor keysdöner LazyMapCollection<[Key : Value], Key>bir ile subscripted edilemez, Int. Bunu halletmenin bir yolu, sözlüğün startIndexalt indislemek istediğiniz tamsayı kadar ilerletmektir, örneğin:

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

Başka bir olası çözüm, bir diziyi keysgirdi olarak başlatmak olabilir, ardından sonuçta tamsayı alt simgelerini kullanabilirsiniz:

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

Unutmayın, sözlükler doğası gereği sırasızdır, bu nedenle belirli bir dizindeki anahtarın her zaman aynı olmasını beklemeyin.


3
Array(myDict)[0].0Anahtarlar dizisini kopyalayamayacağı ve sözlüğün iç yapılarını kopyalayabileceği halde kopyalamaması gerektiği için muhtemelen daha hızlı olacaktır .
David Berry

5
Bunun hangi anahtarın döneceğine dair bir söz olmadığını, ancak döndürülen "görünüm" türü hakkında iyi bir not olduğunu unutmayın. Aslında soru için geçerli olmadığından cevabımı sildim.
Rob Napier

9
Rob'un ne dediğini açıklığa kavuşturmak gerekirse , anahtarlar her seferinde aynı şekilde sipariş ediliyor gibi görünse de, durum böyle değil ve basitçe bir uygulama detayıdır. "Foo" anahtarını eklemeniz çok olasıdır ve dahili gösterim sözlüğü tamamen yeniden düzenleyecektir. Sözlük, anahtar / değer çiftlerinin sıralanmamış bir koleksiyonudur. Bu nedenle, yukarıdaki cevap doğru olmayan tehlikeli varsayımlar yapmaktır.
Jack Lawrence

8
Anahtarlara belirli bir sırayla ihtiyacınız varsa, bir dizi tutun. Sonra onları beğenebilirsin myDict[keysArray[0]].
Zev Eisenberg

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

53

Swift 3: Array()Bunu yapmak faydalı olabilir.

Anahtarı al :

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

Değer elde etmek :

Array(myDict)[index].value

Bu benim için Swift 3 için çalışıyor. Yine de oluşturulan Array'in neden yeniden düzenlendiğini anlamayın. Düşüncesi olan var mı?
Slarty Bartfast

Teşekkürler bu bana yardımcı oldu
ANE

1
@josef Peki ya karşı sezgisel? Sözlükler anahtar, değer çiftleridir, bu nedenle bir dizin fikri sabitlenmez. Dizilere indeks tarafından erişilir, bu nedenle bu bir sözlüğü bir Dizinin içine çevirir ve sonra diziye dizini ile erişir. Gibi bir sözlüğe ["a": 1, "b": 2], bir dizi sözlüğe dönüştürülebilir [[key: "a", value: 1], [key: "b", value: 2]], buna daha sonra indeks ile erişilebilir.
Peter R.

29

Dizine göre sözlükteki anahtarlara ve değerlere erişmek için küçük bir uzantı:

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

3
Swift 2.0 kullanımında 'Advance' API kaldırıldı - self [self.startIndex.advancedBy (i)] -
Romain

2
@TomSawyer sözlükleri sipariş edilmemiştir.
Jose Ramirez

12

Bir sözlüğü yineleyebilir ve for-in ve numaralandırarak bir dizin alabilirsin (diğerlerinin de söylediği gibi, aşağıdaki gibi sıralanacağının garantisi yoktur)

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

Önce sıralamak istiyorsanız ..

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

sonra yineleyin.

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

Sıralı bir sözlük oluşturmak istiyorsanız, Generics'e bakmalısınız.


1
456'ya eşit endeksin ne olduğunu aramak istersem ne olur?
Famic Tech

2
@Max, bu eski Swift sözdizimi. Şimdi şunları kullanabilirsiniz: dict.enumerated().forEach { (index, element) in ... }
Matthew Korporaal

8

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

Bir Array örneğini alan bir API ile bir sözlüğün anahtarlarını veya değerlerini kullanmanız gerekiyorsa, anahtarlar veya değerler özelliğiyle yeni bir dizi başlatın:

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

5

SWIFT 3. İlk eleman için örnek

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

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

3
Ya anahtarın Lehçe olduğu dizini almak istersem?
Famic Tech

5

In Swift 3 Belirtilen dizinde anahtar-değer çifti (lü) almak için bu kodu kullanmayı deneyin:

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

3

İşte Swift 1.2'yi kullanan bir örnek

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


Biraz konu dışı: Ama işte bir Sözlükler Diziniz varsa, yani: [[Dize: Dize]]

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
Örneğinizde age = xxxx olan öğenin indeksini nasıl alabilirim?
Famic Tech

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

@FamicTech, Kris sorunuzu yanıtladı
Suhaib

0

Java'da LinkedHashMap gibi bir şey arıyordum. Yanılmıyorsam ne Swift ne de Objective-C'de bir tane yok.

İlk düşüncem sözlüğümü bir Dizi içine almaktı. [[String: UIImage]]ama sonra sözlükten anahtarı almanın tuhaf olduğunu fark ettim Array(dict)[index].keyve Tuples ile gittim. Şimdi dizim gibi görünüyor, [(String, UIImage)]böylece onu geri alabilirim tuple.0. Artık onu bir Diziye dönüştürmek yok. Sadece 2 sentim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.