ฉันจะรับคีย์ที่ดัชนีเฉพาะจากพจนานุกรมใน Swift ได้อย่างไร


114

ฉันมีDictionaryใน Swift และฉันต้องการรับคีย์ที่ดัชนีเฉพาะ

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

ฉันรู้ว่าฉันสามารถย้ำคีย์และบันทึกได้

for key in myDict.keys{

    NSLog("key = \(key)")

}

อย่างไรก็ตามแปลกพอสิ่งนี้เป็นไปไม่ได้

var key : String = myDict.keys[0]

ทำไม?


11
โปรดทราบว่าพจนานุกรม Swift ไม่ได้รับการรับรองว่าจะเรียงตามลำดับที่เฉพาะเจาะจง ดังนั้นคุณไม่สามารถคาดหวังได้อย่างแน่นอนว่าจะมีการจัดทำดัชนีคีย์ตามลำดับที่คุณใส่ไว้
radex

+1 @radex และต้องการเพิ่มหากเป็นไปได้แหล่งที่มาเพื่ออ่านเพิ่มเติมเกี่ยวกับคำชี้แจงของคุณจะได้รับการชื่นชมอย่างมาก
SH

คำตอบ:


191

นั่นเป็นเพราะkeysผลตอบแทนLazyMapCollection<[Key : Value], Key>ซึ่งไม่สามารถห้อยลงด้วยIntไฟล์. วิธีหนึ่งในการจัดการกับสิ่งนี้คือเลื่อนพจนานุกรมstartIndexด้วยจำนวนเต็มที่คุณต้องการจะห้อยตามตัวอย่างเช่น:

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

อีกวิธีหนึ่งที่เป็นไปได้คือการเริ่มต้นอาร์เรย์ด้วยkeysอินพุตจากนั้นคุณสามารถใช้ตัวห้อยจำนวนเต็มกับผลลัพธ์:

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

จำไว้ว่าพจนานุกรมไม่ได้เรียงลำดับโดยเนื้อแท้ดังนั้นอย่าคาดหวังว่าคีย์ในดัชนีที่กำหนดจะเหมือนกันเสมอไป


3
อาจเร็วกว่านั้นArray(myDict)[0].0เนื่องจากจะไม่คัดลอกอาร์เรย์คีย์และไม่ควรคัดลอกโครงสร้างภายในของพจนานุกรมแม้ว่าอาจจะทำได้
David Berry

5
โปรดทราบว่าไม่มีสัญญาว่าคีย์ใดจะส่งคืน แต่ข้อควรทราบเกี่ยวกับประเภท "มุมมอง" ที่ส่งคืน ลบคำตอบของฉันเนื่องจากไม่ได้ใช้กับคำถามจริง
Rob Napier

9
เพื่อชี้แจงสิ่งที่ Rob กำลังพูดแม้ว่าอาจดูเหมือนว่าคีย์จะเรียงลำดับเหมือนกันทุกครั้ง แต่นี่ไม่ใช่กรณีและเป็นเพียงรายละเอียดการใช้งานเท่านั้น เป็นไปได้มากที่คุณสามารถเพิ่มคีย์ "foo" และการแทนค่าภายในจะเรียงลำดับพจนานุกรมใหม่ทั้งหมด พจนานุกรมคือชุดของคู่คีย์ - ค่าที่ไม่เรียงลำดับ ดังนั้นคำตอบข้างต้นคือการตั้งสมมติฐานที่เป็นอันตรายซึ่งไม่ถือเป็นความจริง
Jack Lawrence

8
หากคุณต้องการคีย์ตามลำดับที่เฉพาะเจาะจงให้เก็บอาร์เรย์ไว้ จากนั้นคุณสามารถใช้พวกเขาเช่นmyDict[keysArray[0]].
Zev Eisenberg

1
ไม่ทำงาน ...'NSDictionary' is not convertible to '_ArrayBuffer<T>'
คริส

53

Swift 3: Array()มีประโยชน์ในการทำเช่นนี้

รับคีย์:

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

รับมูลค่า:

Array(myDict)[index].value

สิ่งนี้ใช้ได้กับฉันสำหรับ Swift 3 ไม่เข้าใจว่าทำไม Array ที่สร้างขึ้นจึงถูกจัดเรียงใหม่ ความคิดใด ๆ ?
Slarty Bartfast

ขอบคุณสิ่งนี้ช่วยฉัน
ANE

1
@josef แล้วเคาน์เตอร์ใช้งานง่ายล่ะ? พจนานุกรมเป็นคีย์คู่ค่าดังนั้นแนวคิดของดัชนีจึงไม่สามารถแก้ไขได้ อาร์เรย์ถูกเข้าถึงโดยดัชนีดังนั้นสิ่งนี้จะเปลี่ยนพจนานุกรมเป็นอาร์เรย์จากนั้นเข้าถึงอาร์เรย์ด้วยดัชนี พจนานุกรมเช่น["a": 1, "b": 2]สามารถเปลี่ยนเป็นอาร์เรย์ของพจนานุกรมเช่น[[key: "a", value: 1], [key: "b", value: 2]]นี้สามารถเข้าถึงได้โดยดัชนี
Peter R

29

นี่คือส่วนขยายขนาดเล็กสำหรับการเข้าถึงคีย์และค่าในพจนานุกรมตามดัชนี:

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

3
API 'advance' ถูกลบออกในการใช้ Swift 2.0 - self [self.startIndex.advancedBy (i)] -
Romain

2
@TomSawyer พจนานุกรมไม่ได้รับคำสั่ง
Jose Ramirez

12

คุณสามารถทำซ้ำในพจนานุกรมและคว้าดัชนีด้วย for-in และแจงนับ (เหมือนที่คนอื่น ๆ พูดไม่มีการรับประกันว่าจะออกมาเรียงลำดับตามด้านล่าง)

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

ถ้าจะเรียงก่อน ..

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

จากนั้นทำซ้ำ

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

หากคุณต้องการสร้างพจนานุกรมตามลำดับคุณควรดู Generics


1
จะเป็นอย่างไรถ้าฉันต้องการค้นหาดัชนีที่มีค่าเท่ากับ 456?
Famic Tech

2
@Max นี่คือไวยากรณ์ Swift แบบเก่า ตอนนี้คุณสามารถใช้: dict.enumerated().forEach { (index, element) in ... }
Matthew Korporaal

8

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

หากคุณจำเป็นต้องใช้คีย์หรือค่าของพจนานุกรมกับ API ที่ใช้อินสแตนซ์ Array ให้เริ่มต้นอาร์เรย์ใหม่ด้วยคุณสมบัติคีย์หรือค่า:

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

5

SWIFT 3. ตัวอย่างสำหรับองค์ประกอบแรก

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

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

3
จะเกิดอะไรขึ้นถ้าฉันต้องการรับดัชนีที่สำคัญคือภาษาโปแลนด์?
Famic Tech

5

ในSwift 3พยายามใช้รหัสนี้เพื่อรับ Key-Value Pair (tuple) ที่ดัชนีที่กำหนด:

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

3

นี่คือตัวอย่างการใช้ 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


นอกประเด็นเล็กน้อย:แต่นี่คือถ้าคุณมี Array of Dictionaries เช่น [[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
ฉันจะรับดัชนีของรายการที่มี age = xxxx ในตัวอย่างของคุณได้อย่างไร
Famic Tech

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

@FamicTech คริสตอบคำถามของคุณ
Suhaib

0

ฉันกำลังมองหาบางอย่างเช่น LinkedHashMap ใน Java ทั้ง Swift และ Objective-C ไม่มีถ้าฉันไม่เข้าใจผิด

ความคิดแรกของฉันคือการรวมพจนานุกรมของฉันไว้ในอาร์เรย์ [[String: UIImage]]แต่แล้วฉันก็รู้ว่าการคว้ากุญแจจากพจนานุกรมเป็นเรื่องแปลกArray(dict)[index].keyฉันจึงไปกับทูเปิลส์ ตอนนี้อาร์เรย์รูปลักษณ์ของฉันเหมือนดังนั้นฉันสามารถเรียกดูได้จาก[(String, UIImage)] tuple.0ไม่มีการแปลงเป็น Array อีกต่อไป แค่ 2 เซ็นต์ของฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.