دیکشنریها یکی از انواع مجموعهی اصلی Swift هستند. یک «دیکشنری» ارتباطهای بدون ترتیب میان کلیدهای یکتا و مقادیر متناظرشان را ذخیره میکند. همهی کلیدهای یک دیکشنری باید از یک نوع باشند و همهی مقادیر هم باید نوع یکسانی داشته باشند.
لیترالهای دیکشنری به شکل جفتهای key: value نوشته میشوند که با کاما از هم جدا شده و داخل کروشه قرار میگیرند:
var addresses: Dictionary<String, String> = [
"The Munsters": "1313 Mockingbird Lane",
"The Simpsons": "742 Evergreen Terrace",
"Buffy Summers": "1630 Revello Drive"
]
var sequences: [String: [Int]] = [
"Euler's totient": [1, 1, 2, 2, 4, 2, 6, 4],
"Lazy caterer": [1, 2, 4, 7, 11, 16, 22, 29, 37],
"Carmichael": [561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841]
]
let constants = [
"pi": 3.14159,
"e": 2.71828,
"phi": 1.618033,
"avogadro": 6.02214076e23
]
نوعهای دیکشنری را میتوان به دو روش صریح نوشت: Dictionary<Key, Value> یا با شکل کوتاه نگارش [Key: Value].
برای ساختن یک دیکشنری خالی، نوع کلید و مقدار آن را بهصراحت مشخص کنید:
var emptyDict1: [Int: Int] = [:]
var emptyDict2 = [Character: String]()
var emptyDict3 = Dictionary<Int, Double>()
میتوانید با استفاده از نماد «اندیس» به مقادیر دسترسی داشته باشید: کلید را داخل کروشه، بعد از اسم دیکشنری قرار دهید.
از آنجا که ممکن است یک کلید در دیکشنری وجود نداشته باشد، دسترسی با اندیس یک مقدار اختیاری (Value?) برمیگرداند.
اگر کلید وجود داشته باشد، Swift مقدار پوششدادهشده را برمیگرداند؛ در غیر این صورت nil را برمیگرداند:
let munster: String? = addresses["The Munsters"]
// Returns Optional("1313 Mockingbird Lane")
let carmichael = sequences["Carmichael"]
// Returns Optional([561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841])
let planck = constants["planck"]
// Returns nil
برای اینکه مجبور نباشید با مقدارهای اختیاری کار کنید، میتوانید با استفاده از پارامتر default یک مقدار پیشفرض بدهید:
let e: Double = constants["e", default: 0]
// Returns 2.71828
let hoagie: [Int] = sequences["Hoagie", default: []]
// Returns []
let betty = addresses["Betty Cooper", default: "Address unknown"]
// Returns "Address unknown"
برای دیکشنریهای قابل تغییر که با var تعریف شدهاند، میتوانید جفتهای کلید-مقدار را با انتساب از طریق اندیس اضافه یا بهروزرسانی کنید:
sequences["Euler's totient"]?.append(contentsOf: [6, 4])
// sequences["Euler's totient"] is now [1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
addresses["Betty Cooper"] = "111 Queens Ave."
addresses["Betty Cooper", default: "Address unknown"]
// Returns "111 Queens Ave."
constants["Gelfond's"] = 23.140692
// Compiler error: Cannot assign through subscript: 'constants' is a 'let' constant
میتوانید با استفاده از یک حلقهی for-in روی هر جفت کلید-مقدار یک دیکشنری پیمایش کنید.
هر عنصر بهصورت یک «تاپل» (key, value) در اختیار شما قرار میگیرد:
for (name, address) in addresses {
print("\(name) lives at \(address)")
}
چون دیکشنریها بدون ترتیباند، مرتب کردنشان یک آرایه از جفتهای کلید-مقدار تولید میکند.
میتوانید یک «کلوژر» به متد sorted(by:) بدهید که دو تاپل (key, value) را مقایسه میکند و اگر تاپل اول باید قبل از دومی بیاید true برمیگرداند:
func sortByNameLengthThenValue(_ lhs: (key: String, value: Double), _ rhs: (key: String, value: Double)) -> Bool {
let left = lhs.value + Double(lhs.key.count)
let right = rhs.value + Double(rhs.key.count)
return left < right
}
let sortedConstants = constants.sorted(by: sortByNameLengthThenValue)
در این تمرین، روشی را پیادهسازی میکنید که امتیازهای بالای محبوبترین بازی در سالن بازیهای آرکید محلهتان را ثبت کند.
شما باید ۷ تابع پیادهسازی کنید که همه به برگرداندن و دستکاری یک «دیکشنری» از دادههای امتیازهای بالا مربوط میشوند.
تابعی به نام newScoreBoard() ایجاد کنید که هیچ پارامتری نمیگیرد و یک دیکشنری جدید امتیاز بالا برمیگرداند که برای کلیدها از مقادیری از نوع String و به عنوان مقدارها از مقادیری از نوع Int استفاده میکند.
برای افزودن بازیکن به دیکشنری امتیاز بالا، تابع addPlayer(_:_:_:) را تعریف کنید. این تابع ۳ پارامتر میگیرد:
var highScores = newScoreBoard()
addPlayer(&highScores, "Dave Thomas")
// Returns ["Dave Thomas": 0]
addPlayer(&highScores, "José Valim", 486_373)
// Returns ["Dave Thomas": 0, "José Valim": 486_373]
برای حذف بازیکن از دیکشنری امتیاز بالا، removePlayer(_:_:) را تعریف کنید. این تابع ۲ پارامتر میگیرد:
این تابع باید بازیکن را، در صورتی که در دیکشنری باشد، از آن حذف کند و در غیر این صورت کاری انجام ندهد.
var highScores = ["Dave Thomas": 0, "José Valim": 486_373]
removePlayer(&highScores, "Dave Thomas")
// Returns ["José Valim": 486_373]
removePlayer(&highScores, "Rose Fanaras")
// Returns ["José Valim": 486_373]
برای بازنشانی امتیاز یک بازیکن، resetPlayer(_:_:) را تعریف کنید. این تابع ۲ پارامتر میگیرد:
این تابع امتیاز بازیکن را روی ۰ تنظیم میکند. اگر بازیکن در دیکشنری نباشد، نباید اتفاقی بیفتد.
var highScores = ["Dave Thomas": 486_373, "José Valim": 10]
resetScore(&highScores, "Dave Thomas")
// Returns ["Dave Thomas": 0, "José Valim": 10]
برای بهروزرسانی امتیاز یک بازیکن با افزودن به امتیاز قبلی، updateScore را تعریف کنید. این تابع ۳ پارامتر میگیرد:
var highScores = ["Dave Thomas": 0, "José Valim": 486_373]
addPlayer(&highScores, "Freyja Ćirić", 12_771_008)
updateScore(&highScores, "Freyja Ćirić", 73)
// Returns ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_081]
تابع orderByPlayers را تعریف کنید که ۱ پارامتر میگیرد:
این تابع یک آرایه از تاپلهای (String, Int) را برمیگرداند که همان بازیکنها و امتیازهای بالایشان هستند و بر اساس اسم بازیکن به ترتیب صعودی مرتب شدهاند.
var highScores = ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_091]
orderByPlayers(highScores)
// Returns [("Dave Thomas", 0), ("Freyja Ćirić", 12_771_091), ("José Valim", 486_373)]
برای دریافت فهرستی از بازیکنها که بر اساس امتیازها به ترتیب نزولی مرتب شدهاند، orderByScores را تعریف کنید که ۱ پارامتر میگیرد:
این تابع یک آرایه از تاپلهای (String, Int) را برمیگرداند که همان بازیکنها و امتیازهای بالایشان هستند و بر اساس امتیاز بازیکن به ترتیب نزولی مرتب شدهاند.
var highScores = ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_091]
orderByScores(highScores)
// Returns [("Freyja Ćirić", 12_771_091), ("José Valim", 486_373), ("Dave Thomas", 0)]