问题描述
struct Data {
let storage: [String: Int]
init(_ pairs: keyvaluePairs<String,Int>) {
storage = Dictionary(uniqueKeysWithValues: pairs)
}
}
编译错误:
初始化器'init(uniqueKeysWithValues :)'需要类型 'keyvaluePairs
.Element'(aka'(键:字符串,值:Int)') 和'(String,Int)'等价
有什么比用keyvaluePairs初始化Dictionary(uniqueKeysWithValues :)更自然的呢?不可能直接做只是荒谬的!requires '(key: String,value: Int)' and '(String,Int)' be equivalent
等同!
解决方法
这是因为KeyValuePairs.Element有标签。
type(of: (key: "",value: 0)) == type(of: ("",0)) // false
您需要另一个重载或仅就地移除标签。
public extension Dictionary {
/// Creates a new dictionary from the key-value pairs in the given sequence.
///
/// - Parameter keysAndValues: A sequence of key-value pairs to use for
/// the new dictionary. Every key in `keysAndValues` must be unique.
/// - Returns: A new dictionary initialized with the elements of
/// `keysAndValues`.
/// - Precondition: The sequence must not have duplicate keys.
@inlinable init<Elements: Sequence>(uniqueKeysWithValues keysAndValues: Elements)
where Elements.Element == Element {
self.init(
uniqueKeysWithValues: keysAndValues.map { ($0,$1) }
)
}
}
XCTAssertEqual(
Dictionary(
uniqueKeysWithValues: ["?": "?","?♀️": "?♂️"] as KeyValuePairs
),.init(
uniqueKeysWithValues: [("?","?"),("?♀️","?♂️")]
)
)
,
您也可以使用reduce
:
storage = pairs.reduce(into: [String: Int]()) { $0[$1.key] = $1.value }
即使您在pairs
中有重复的键,这也将起作用(当前,它从重复项中取出最后一项:
let data = Data(["a": 1,"b": 2,"a": 3] as KeyValuePairs)
print(data.storage)
// ["a": 3,"b": 2]
如果需要它来带走第一件物品,您可以这样做:
storage = pairs.reduce(into: [String: Int]()) { $0[$1.key] = $0[$1.key] ?? $1.value }
(或更短)
storage = pairs.reduce(into: [String: Int]()) { $0[$1.0] = $0[$1.0] ?? $1.1 }
此打印:
let data = Data(["a": 1,"a": 3] as KeyValuePairs)
print(data.storage)
// ["a": 1,"b": 2]
,
由于Swift不支持 Splatting (尚未),因此您可以通过以下方式实现它:
struct Data {
let storage: [String: Int]
init(_ pairs: KeyValuePairs<String,Int>) {
storage = Dictionary(uniqueKeysWithValues: pairs.reduce(into: [String: Int]()) { $0[$1.0] = $1.1 } .map { $0 })
}
}
用法:
let data = Data(KeyValuePairs(dictionaryLiteral: ("a",1),("b",2)))
,
•修复:
storage = Dictionary(uniqueKeysWithValues: Array(pairs))
•原因:
您尝试使用的方法是:
public init<S>(uniqueKeysWithValues keysAndValues: S) where S : Sequence,S.Element == (Key,Value)
它缺少S.Element == (Key,Value)
的合规性。
•再进一步一点:
请注意,如果您有重复的键,则会出现错误。您可以使用:
storage = Dictionary(Array(paris)) { _,new in
return new //if you want to keep the last "key" value,or the reverse
}
•其他可能性:
convert [(key: String,value: String)] in [String:String]