交换键和值的字典扩展 - Swift 4.1
Dictionary Extension that Swaps Keys & Values - Swift 4.1
词典扩展 - 交换词典键和值
Swift4.1,Xcode9.3
我想创建一个函数,它将接受 Dictionary
和 return 所述字典,但将其值作为键,将其键作为其各自的值。到目前为止,我已经创建了一个函数来执行此操作,但我无法终生将它变成 Dictionary
的 extension
。
我的函数
func swapKeyValues<T, U>(of dict: [T : U]) -> [U : T] {
let arrKeys = Array(dict.keys)
let arrValues = Array(dict.values)
var newDict = [U : T]()
for (i,n) in arrValues.enumerated() {
newDict[n] = arrKeys[i]
}
return newDict
}
使用示例:
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
let newDict = swapKeyValues(of: dict)
print(newDict) //["b": 2, "e": 5, "a": 1, "d": 4, "c": 3]
理想:
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
//I would like the function in the extension to be called swapped()
print(dict.swapped()) //["b": 2, "e": 5, "a": 1, "d": 4, "c": 3]
如何实现这个理想?
明确地说,除非值符合 Hashable
协议,否则您所要求的是不可能的。所以,有条件的延期就是您要找的。
extension Dictionary where Value: Hashable {
func keyValueSwapped() -> [Value:Key] {
var newDict = [Value:Key]()
keys.forEach { (key) in
let value = self[key]!
newDict[value] = key
}
return newDict
}
}
Dictionary 的扩展可能是这样的,成为键的 value
必须限制为 Hashable
extension Dictionary where Value : Hashable {
func swapKeyValues() -> [Value : Key] {
assert(Set(self.values).count == self.keys.count, "Values must be unique")
var newDict = [Value : Key]()
for (key, value) in self {
newDict[value] = key
}
return newDict
}
}
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
let newDict = dict.swapKeyValues()
print(newDict)
正如其他答案中已经解释的那样,Value
类型必须是
限制为Hashable
,否则不能为Key
新词典。
还必须决定如何在源字典中重复值
应该处理。
为了实现,可以将源字典映射到
交换键和值的序列,并将其传递给
初始值设定项之一
它们在处理重复键的方式上有所不同:第一个中止
有一个运行时异常,第二个调用闭包
解决冲突。
所以一个简单的实现是
extension Dictionary where Value: Hashable {
func swapKeyValues() -> [Value : Key] {
return Dictionary<Value, Key>(uniqueKeysWithValues: lazy.map { ([=10=].value, [=10=].key) })
}
}
(映射源字典 lazily 避免创建一个
所有交换 key/value 元组的中间数组。)
示例:
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
print(dict.swapKeyValues()) //["b": 2, "e": 5, "a": 1, "d": 4, "c": 3]
如果源字典有重复值,这将崩溃。
这是一个接受源中重复值的变体
字典(“后来”的值会覆盖“较早”的值):
extension Dictionary where Value: Hashable {
func swapKeyValues() -> [Value : Key] {
return Dictionary<Value, Key>(lazy.map { ([=12=].value, [=12=].key) }, uniquingKeysWith: { })
}
}
示例:
let dict = [1 : "a", 2 : "b", 3 : "b"]
print(dict.swapKeyValues()) // ["b": 3, "a": 1]
另一种选择是将其实现为字典
初始值设定项。例如:
extension Dictionary where Value: Hashable {
init?(swappingKeysAndValues dict: [Value: Key]) {
self.init(uniqueKeysWithValues: dict.lazy.map( { ([=14=].value, [=14=].key) }))
}
}
在源字典中出现重复值的情况下崩溃,
或者作为抛出初始化器
extension Dictionary where Value: Hashable {
struct DuplicateValuesError: Error, LocalizedError {
var errorDescription: String? {
return "duplicate value"
}
}
init(swappingKeysAndValues dict: [Value: Key]) throws {
try self.init(dict.lazy.map { ([=15=].value, [=15=].key) },
uniquingKeysWith: { _,_ in throw DuplicateValuesError() })
}
}
或作为可失败的初始化器:
extension Dictionary where Value: Hashable {
struct DuplicateValuesError: Error { }
init?(swappingKeysAndValues dict: [Value: Key]) {
do {
try self.init(dict.lazy.map { ([=16=].value, [=16=].key) },
uniquingKeysWith: { _,_ in throw DuplicateValuesError() })
} catch {
return nil
}
}
}
示例(对于可失败初始化器):
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
if let newDict = Dictionary(swappingKeysAndValues: dict) {
print(newDict) //["b": 2, "e": 5, "a": 1, "d": 4, "c": 3]
}
或者,如果您确定不会出现重复值:
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
let newDict = Dictionary(swappingKeysAndValues: dict)!
您可以映射字典以交换键和值,并使用 Dictionary(uniqueKeysWithValues:)
初始值设定项创建一个新字典:
let dict = ["Key1": "Value1", "Key2": "Value2", ...]
let swappedDict = Dictionary(uniqueKeysWithValues: dict.map {(key, value) in return (value, key)})
请注意 Value
类型应符合 Hashable 协议,并且初始化程序会在重复键的情况下抛出运行时异常。如果原始字典可能有重复值,请改用 Dictionary(_:uniquingKeysWith:)
初始值设定项。
词典扩展 - 交换词典键和值
Swift4.1,Xcode9.3
我想创建一个函数,它将接受 Dictionary
和 return 所述字典,但将其值作为键,将其键作为其各自的值。到目前为止,我已经创建了一个函数来执行此操作,但我无法终生将它变成 Dictionary
的 extension
。
我的函数
func swapKeyValues<T, U>(of dict: [T : U]) -> [U : T] {
let arrKeys = Array(dict.keys)
let arrValues = Array(dict.values)
var newDict = [U : T]()
for (i,n) in arrValues.enumerated() {
newDict[n] = arrKeys[i]
}
return newDict
}
使用示例:
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
let newDict = swapKeyValues(of: dict)
print(newDict) //["b": 2, "e": 5, "a": 1, "d": 4, "c": 3]
理想:
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
//I would like the function in the extension to be called swapped()
print(dict.swapped()) //["b": 2, "e": 5, "a": 1, "d": 4, "c": 3]
如何实现这个理想?
明确地说,除非值符合 Hashable
协议,否则您所要求的是不可能的。所以,有条件的延期就是您要找的。
extension Dictionary where Value: Hashable {
func keyValueSwapped() -> [Value:Key] {
var newDict = [Value:Key]()
keys.forEach { (key) in
let value = self[key]!
newDict[value] = key
}
return newDict
}
}
Dictionary 的扩展可能是这样的,成为键的 value
必须限制为 Hashable
extension Dictionary where Value : Hashable {
func swapKeyValues() -> [Value : Key] {
assert(Set(self.values).count == self.keys.count, "Values must be unique")
var newDict = [Value : Key]()
for (key, value) in self {
newDict[value] = key
}
return newDict
}
}
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
let newDict = dict.swapKeyValues()
print(newDict)
正如其他答案中已经解释的那样,Value
类型必须是
限制为Hashable
,否则不能为Key
新词典。
还必须决定如何在源字典中重复值 应该处理。
为了实现,可以将源字典映射到 交换键和值的序列,并将其传递给 初始值设定项之一
它们在处理重复键的方式上有所不同:第一个中止 有一个运行时异常,第二个调用闭包 解决冲突。
所以一个简单的实现是
extension Dictionary where Value: Hashable {
func swapKeyValues() -> [Value : Key] {
return Dictionary<Value, Key>(uniqueKeysWithValues: lazy.map { ([=10=].value, [=10=].key) })
}
}
(映射源字典 lazily 避免创建一个 所有交换 key/value 元组的中间数组。)
示例:
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
print(dict.swapKeyValues()) //["b": 2, "e": 5, "a": 1, "d": 4, "c": 3]
如果源字典有重复值,这将崩溃。 这是一个接受源中重复值的变体 字典(“后来”的值会覆盖“较早”的值):
extension Dictionary where Value: Hashable {
func swapKeyValues() -> [Value : Key] {
return Dictionary<Value, Key>(lazy.map { ([=12=].value, [=12=].key) }, uniquingKeysWith: { })
}
}
示例:
let dict = [1 : "a", 2 : "b", 3 : "b"]
print(dict.swapKeyValues()) // ["b": 3, "a": 1]
另一种选择是将其实现为字典 初始值设定项。例如:
extension Dictionary where Value: Hashable {
init?(swappingKeysAndValues dict: [Value: Key]) {
self.init(uniqueKeysWithValues: dict.lazy.map( { ([=14=].value, [=14=].key) }))
}
}
在源字典中出现重复值的情况下崩溃, 或者作为抛出初始化器
extension Dictionary where Value: Hashable {
struct DuplicateValuesError: Error, LocalizedError {
var errorDescription: String? {
return "duplicate value"
}
}
init(swappingKeysAndValues dict: [Value: Key]) throws {
try self.init(dict.lazy.map { ([=15=].value, [=15=].key) },
uniquingKeysWith: { _,_ in throw DuplicateValuesError() })
}
}
或作为可失败的初始化器:
extension Dictionary where Value: Hashable {
struct DuplicateValuesError: Error { }
init?(swappingKeysAndValues dict: [Value: Key]) {
do {
try self.init(dict.lazy.map { ([=16=].value, [=16=].key) },
uniquingKeysWith: { _,_ in throw DuplicateValuesError() })
} catch {
return nil
}
}
}
示例(对于可失败初始化器):
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
if let newDict = Dictionary(swappingKeysAndValues: dict) {
print(newDict) //["b": 2, "e": 5, "a": 1, "d": 4, "c": 3]
}
或者,如果您确定不会出现重复值:
let dict = [1 : "a", 2 : "b", 3 : "c", 4 : "d", 5 : "e"]
let newDict = Dictionary(swappingKeysAndValues: dict)!
您可以映射字典以交换键和值,并使用 Dictionary(uniqueKeysWithValues:)
初始值设定项创建一个新字典:
let dict = ["Key1": "Value1", "Key2": "Value2", ...]
let swappedDict = Dictionary(uniqueKeysWithValues: dict.map {(key, value) in return (value, key)})
请注意 Value
类型应符合 Hashable 协议,并且初始化程序会在重复键的情况下抛出运行时异常。如果原始字典可能有重复值,请改用 Dictionary(_:uniquingKeysWith:)
初始值设定项。