Swift中如何传入Dictionary.Element以数组字面量初始化字典
Swift 直接传入键值对元素初始化字典的实现方法
首先说明你之前几种写法报错的核心原因:
- 第一种无标注闭包写法报异构集合错误:一方面你闭包返回的元组标签是
s,和Dictionary.Element要求的(key: Key, value: Value)标签不匹配;另一方面编译器不会自动把多语句闭包返回的元组推断为字典键值对类型,多个闭包返回值组成的数组字面量找不到统一的元素类型,只能被推断为[Any] - 第二种加类型标注的写法报错有两个问题:一是你把变量
v的类型声明成了Dictionary<String, T>.Element,也就是单个键值对的类型,不是字典本身;二是就算把类型改成Dictionary<String, T>,标准库默认的Dictionary也没有实现用键值对数组字面量直接初始化的逻辑,自然会报初始化错误。
你要的「把Dictionary.Element(键值对整体)像数组元素一样传入直接初始化字典」的需求是可以实现的,有两种通用方案:
方案1:使用标准库自带的序列初始化方法(推荐)
Swift 标准库的Dictionary原生提供了两个接收键值对序列的初始化方法,不需要写任何扩展就能用:
init(uniqueKeysWithValues:):适用于所有键都不重复的场景,和你示例里的用法完全匹配init(_:uniquingKeysWith:):适用于可能存在重复键的场景,需要传入一个闭包处理键冲突时的取值逻辑
你的闭包写法套上这个方法就能正常运行:
// 键无重复时的写法,和你预期的逻辑完全一致 var v = Dictionary(uniqueKeysWithValues: [ { let s = "x"; return (s, T(name: s)) }(), { let s = "y"; return (s, T(name: s)) }() ])
这里的元组不需要特意加标签,也不需要手动构造Dictionary.Element类型,只要是和字典键值类型匹配的(Key, Value)元组,编译器就能自动识别。
方案2:扩展字典支持数组字面量直接初始化
如果你想完全省略外层的初始化方法,写得和数组字面量格式完全一致,可以给Dictionary添加扩展,让它支持以键值对元素为内容的数组字面量初始化:
extension Dictionary: ExpressibleByArrayLiteral { public init(arrayLiteral elements: Element...) { // 如果需要处理键重复,可以替换成带冲突闭包的初始化方法 self.init(uniqueKeysWithValues: elements) } }
添加完这个扩展后,你想要的字面量写法就能直接生效:
// 扩展后可直接编译运行 var v: Dictionary<String, T> = [ { let s = "x"; return (s, T(name: s)) }(), { let s = "y"; return (s, T(name: s)) }() ]
注意:这个扩展会全局修改字典的字面量初始化逻辑,如果项目规模较大,可能和其他类型推断逻辑产生冲突,生产环境更推荐使用第一种标准库原生方案。
内容的提问来源于stack exchange,提问作者mrchance
相关产品推荐
相关产品推荐

