HoRain云--Swift字典完全指南

张开发
2026/4/13 12:49:40 15 分钟阅读

分享文章

HoRain云--Swift字典完全指南
HoRain 云小助手个人主页⛺️生活的理想就是为了理想的生活!⛳️ 推荐前些天发现了一个超棒的服务器购买网站性价比超高大内存超划算忍不住分享一下给大家。点击跳转到网站。目录⛳️ 推荐Swift 字典详解基本用法字典的创建和初始化访问和修改字典检查字典状态遍历字典基本遍历获取键和值的数组字典的高级操作合并字典过滤字典映射字典分组字典的默认值字典与集合操作自定义类型作为字典的键性能优化技巧1. 预估容量2. 避免不必要的复制3. 使用 lazy 延迟计算字典的实际应用示例1统计词频示例2缓存计算结果示例3配置管理字典 vs 数组 vs 集合注意事项最佳实践Swift 字典详解Swift 字典是一种存储无序键值对集合的数据结构所有键的类型相同所有值的类型相同。每个键是唯一的用于标识对应的值。基本用法字典的创建和初始化// 1. 创建空字典 var emptyDict1: [String: Int] [:] var emptyDict2 [String: Int]() var emptyDict3 DictionaryString, Int() // 2. 使用字面量创建 var airports: [String: String] [ YYZ: Toronto Pearson, DUB: Dublin, LHR: London Heathrow ] // 类型推断 var airports2 [ YYZ: Toronto Pearson, DUB: Dublin ] // 类型推断为 [String: String] // 3. 包含重复键后面的会覆盖前面的 var dictWithDuplicates [ A: 1, B: 2, A: 3 // 会覆盖前面的 A: 1 ] print(dictWithDuplicates) // [A: 3, B: 2]访问和修改字典var studentScores [ Alice: 95, Bob: 87, Charlie: 92 ] // 1. 通过键访问值返回可选类型 if let aliceScore studentScores[Alice] { print(Alice的分数是: \(aliceScore)) } // 2. 修改值 studentScores[Alice] 100 // 更新 studentScores[David] 88 // 添加新键值对 // 3. 使用 updateValue(_:forKey:) 方法 // 返回旧值可选类型如果键不存在则添加并返回nil if let oldValue studentScores.updateValue(90, forKey: Bob) { print(Bob的分数从 \(oldValue) 改为 90) } if let oldValue studentScores.updateValue(85, forKey: Eve) { print(Eve的旧分数: \(oldValue)) } else { print(Eve是新生添加了分数 85) } // 4. 删除键值对 studentScores[Charlie] nil // 直接赋值为nil if let removedValue studentScores.removeValue(forKey: Bob) { print(删除了Bob他的分数是 \(removedValue)) } // 5. 删除所有元素 studentScores.removeAll() // 或者 studentScores [:]检查字典状态var dict [a: 1, b: 2, c: 3] // 1. 检查是否为空 if dict.isEmpty { print(字典为空) } else { print(字典有 \(dict.count) 个元素) } // 2. 检查键是否存在 if dict.keys.contains(a) { print(字典包含键 a) } // 3. 检查值是否存在 if dict.values.contains(2) { print(字典包含值 2) }遍历字典基本遍历let capitals [ 中国: 北京, 美国: 华盛顿, 日本: 东京, 法国: 巴黎 ] // 1. 遍历键值对 for (country, capital) in capitals { print(\(country)的首都是 \(capital)) } // 2. 只遍历键 for country in capitals.keys { print(国家: \(country)) } // 3. 只遍历值 for capital in capitals.values { print(首都: \(capital)) } // 4. 使用 forEach capitals.forEach { country, capital in print(\(country)的首都是 \(capital)) }获取键和值的数组let dict [a: 1, b: 2, c: 3] // 获取键的数组 let keys Array(dict.keys) // [a, b, c] let sortedKeys dict.keys.sorted() // 排序后的键数组 // 获取值的数组 let values Array(dict.values) // [1, 2, 3] let sortedValues dict.values.sorted() // 排序后的值数组 // 注意字典是无序的所以每次获取的顺序可能不同字典的高级操作合并字典var dict1 [a: 1, b: 2] var dict2 [b: 3, c: 4] // 注意b会覆盖dict1中的b // 1. 使用 merging 方法返回新字典 let merged1 dict1.merging(dict2) { (current, _) in return current // 保留原有值 } print(merged1) // [a: 1, b: 2, c: 4] let merged2 dict1.merging(dict2) { (_, new) in return new // 使用新值 } print(merged2) // [a: 1, b: 3, c: 4] // 2. 使用 merging 方法并指定合并策略 let merged3 dict1.merging(dict2, uniquingKeysWith: { $0 $1 }) // 相同键的值相加 print(merged3) // [a: 1, b: 5, c: 4] // 3. 原地合并 dict1.merge(dict2) { (current, new) in new } // 原地修改dict1 print(dict1) // [a: 1, b: 3, c: 4]过滤字典let scores [ Alice: 95, Bob: 87, Charlie: 92, David: 76, Eve: 65 ] // 1. 过滤出分数大于90的学生 let highScores scores.filter { $0.value 90 } print(highScores) // [Charlie: 92, Alice: 95] // 2. 过滤出名字以A或B开头的学生 let filteredNames scores.filter { $0.key.hasPrefix(A) || $0.key.hasPrefix(B) } print(filteredNames) // [Bob: 87, Alice: 95] // 3. 使用 where 条件 let averageScores scores.filter { name, score in return score 80 score 90 } print(averageScores) // [Bob: 87]映射字典let prices [apple: 1.0, banana: 0.5, orange: 0.8] // 1. 映射值 let discountedPrices prices.mapValues { price in return price * 0.8 // 打8折 } print(discountedPrices) // [apple: 0.8, banana: 0.4, orange: 0.64] // 2. 映射键值对 let productInfo prices.map { (fruit, price) in return \(fruit): $\(price) } print(productInfo) // [apple: $1.0, banana: $0.5, orange: $0.8] // 3. 紧凑映射过滤nil let optionalDict [a: 1, b: two, c: 3] let intDict optionalDict.compactMapValues { Int($0) } print(intDict) // [a: 1, c: 3] // two无法转换为Int被过滤掉分组let students [ Alice: 95, Bob: 87, Charlie: 92, David: 76, Eve: 65, Frank: 88 ] // 1. 按分数范围分组 let groupedByScore Dictionary(grouping: students) { (name, score) in switch score { case 90...100: return 优秀 case 80..90: return 良好 case 60..80: return 及格 default: return 不及格 } } print(groupedByScore) // [良好: [Bob: 87, Frank: 88], 优秀: [Alice: 95, Charlie: 92], 及格: [David: 76, Eve: 65]] // 2. 按首字母分组 let groupedByInitial Dictionary(grouping: students.keys) { name in return String(name.first!) } print(groupedByInitial) // [A: [Alice], B: [Bob], C: [Charlie], D: [David], E: [Eve], F: [Frank]]字典的默认值// 1. 使用下标访问时的默认值 var wordCount [String: Int]() // 传统方式 let word hello if let count wordCount[word] { wordCount[word] count 1 } else { wordCount[word] 1 } // 使用默认值 wordCount[world, default: 0] 1 // 相当于wordCount[world] (wordCount[world] ?? 0) 1 // 2. 合并时使用默认值 var left [a: 1, b: 2] let right [b: 3, c: 4] let merged right.reduce(into: left) { result, pair in let (key, value) pair result[key, default: 0] value } print(merged) // [a: 1, b: 5, c: 4]字典与集合操作let dict1 [a: 1, b: 2, c: 3] let dict2 [b: 2, c: 4, d: 5] // 1. 获取共同的键 let commonKeys Set(dict1.keys).intersection(dict2.keys) print(commonKeys) // [b, c] // 2. 获取所有键 let allKeys Set(dict1.keys).union(dict2.keys) print(allKeys) // [a, b, c, d] // 3. 获取不同的键 let uniqueKeys1 Set(dict1.keys).subtracting(dict2.keys) let uniqueKeys2 Set(dict2.keys).subtracting(dict1.keys) print(uniqueKeys1) // [a] print(uniqueKeys2) // [d]自定义类型作为字典的键要使自定义类型作为字典的键必须遵循Hashable协议struct Coordinate: Hashable { let x: Int let y: Int // Hashable 协议要求实现 hash(into:) 方法 func hash(into hasher: inout Hasher) { hasher.combine(x) hasher.combine(y) } // Equatable 协议Hashable 继承自 Equatable static func (lhs: Coordinate, rhs: Coordinate) - Bool { return lhs.x rhs.x lhs.y rhs.y } } // 使用自定义类型作为键 var grid [Coordinate: String]() grid[Coordinate(x: 0, y: 0)] 起点 grid[Coordinate(x: 1, y: 1)] 宝藏 print(grid[Coordinate(x: 0, y: 0)]!) // 起点 // 对于枚举默认就是 Hashable 的 enum Direction: Hashable { case north, south, east, west } var directions [Direction: String]() directions[.north] 向上 print(directions[.north]!) // 向上性能优化技巧1. 预估容量// 如果你知道字典的大致大小可以预先分配容量以提高性能 var largeDict [String: Int](minimumCapacity: 1000) for i in 0..1000 { largeDict[key\(i)] i }2. 避免不必要的复制// Swift字典是值类型但使用了写时复制Copy-on-Write优化 var original [a: 1, b: 2] var copy original // 此时不会复制共享存储 copy[c] 3 // 这时才会复制 print(original) // [a: 1, b: 2] print(copy) // [a: 1, b: 2, c: 3]3. 使用 lazy 延迟计算let expensiveDict [a: expensiveComputation1(), b: expensiveComputation2()] // 如果某些值可能不会被访问使用延迟计算 let lazyDict [ a: { expensiveComputation1() }, b: { expensiveComputation2() } ] // 只有在需要时才计算 let result lazyDict[a]?() // 只有这时才计算字典的实际应用示例1统计词频func wordFrequency(_ text: String) - [String: Int] { var frequency [String: Int]() let words text.lowercased().split { !$0.isLetter } for word in words { let wordStr String(word) frequency[wordStr, default: 0] 1 } return frequency } let text Hello world hello everyone world let freq wordFrequency(text) print(freq) // [hello: 2, world: 2, everyone: 1]示例2缓存计算结果struct Fibonacci { private var cache [Int: Int]() mutating func calculate(_ n: Int) - Int { if n 1 { return n } // 检查缓存 if let cached cache[n] { return cached } // 计算并缓存结果 let result calculate(n - 1) calculate(n - 2) cache[n] result return result } } var fib Fibonacci() print(fib.calculate(10)) // 55示例3配置管理struct AppConfig { private var config: [String: Any] [ apiUrl: https://api.example.com, timeout: 30, retryCount: 3, debugMode: false ] func getT(_ key: String) - T? { return config[key] as? T } mutating func setT(_ key: String, value: T) { config[key] value } } var config AppConfig() let url: String? config.get(apiUrl) let timeout: Int? config.get(timeout) config.set(timeout, value: 60)字典 vs 数组 vs 集合特性字典数组集合顺序无序有序无序重复键唯一元素可重复元素唯一访问通过键O(1)平均通过索引O(1)通过元素O(1)平均查找快O(1)平均慢O(n)快O(1)平均内存较高较低较高适用场景键值映射、缓存有序列表、队列唯一性检查、集合运算注意事项字典是无序的不要依赖字典的顺序如果需要有序使用Array或对字典排序键必须是 Hashable 的所有键的类型必须遵循Hashable协议字典是值类型赋值和传递时会被复制但 Swift 会优化可选类型的值通过下标访问返回可选类型需要解包线程安全Swift 字典不是线程安全的多线程访问需要同步最佳实践使用默认值避免频繁的可选绑定预估容量当你知道大小时使用minimumCapacity参数使用mapValues和compactMapValues对值进行转换时更高效优先使用值类型如果值很小值类型比引用类型性能更好考虑使用NSDictionary如果需要与 Objective-C 交互Swift 字典是一个强大灵活的数据结构合理使用可以大大提高代码的效率和可读性。❤️❤️❤️本人水平有限如有纰漏欢迎各位大佬评论批评指正如果觉得这篇文对你有帮助的话也请给个点赞、收藏下吧非常感谢! Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧

更多文章