我有一个Set
实例,想要将其放入Dictionary
,并将其与多个密钥相关联,以便将来查找/修改它。
以下Python代码是我想在Swift中实现的。
s = set()
D = {}
D["a"] = s
D["b"] = s
D["a"].add("Hello")
D["a"].add("World")
print(D["b"]) # getting {"Hello", "World"} back
我在Swift中尝试了类似的内容。
var s = Set<String>()
var D = Dictionary<String, Set<String>>()
D["a"] = s // copy of s is assigned
D["b"] = s // another copy of s is assigned
D["a"]!.insert("Hello")
D["a"]!.insert("World")
print(D["b"]!) // empty :(
由于Swift中的集合保持了值语义,所以当我将一个集合放入字典时,就会创建新的实例。有没有解决方法?我知道我可以使用NSMutableSet
而不是Swift的Set
,但我想知道如果可能的话,我可以通过使用带有值语义的集合来解决这个问题。
答案 0 :(得分:4)
啊!现在我们了解它的核心。您只需要一个基于stdlib的引用类型,而不是使用Foundation提供的引用类型。如果稍微单调乏味,那就很容易实现。只需在一个类中包装一个Set。如果您不想完全SetAlgebra
或Collection
一致,则不必实施所有这些方法。 (并且您可能需要更多init
方法来使这更方便,但希望这些实现在您的代码需求中非常明显。)
final class RefSet<Element> where Element: Hashable {
private var storage: Set<Element> = Set()
init() {}
}
extension RefSet: Equatable where Element: Equatable {
static func == (lhs: RefSet<Element>, rhs: RefSet<Element>) -> Bool {
return lhs.storage == rhs.storage
}
}
extension RefSet: SetAlgebra {
var isEmpty: Bool { return storage.isEmpty }
func contains(_ member: Element) -> Bool {
return storage.contains(member)
}
func union(_ other: RefSet<Element>) -> RefSet<Element> {
return RefSet(storage.union(other.storage))
}
func intersection(_ other: RefSet<Element>) -> RefSet<Element> {
return RefSet(storage.intersection(other.storage))
}
func symmetricDifference(_ other: RefSet<Element>) -> RefSet<Element> {
return RefSet(storage.symmetricDifference(other.storage))
}
@discardableResult
func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element) {
return storage.insert(newMember)
}
@discardableResult
func remove(_ member: Element) -> Element? {
return storage.remove(member)
}
@discardableResult
func update(with newMember: Element) -> Element? {
return storage.update(with: newMember)
}
func formUnion(_ other: RefSet<Element>) {
storage.formUnion(other.storage)
}
func formIntersection(_ other: RefSet<Element>) {
storage.formIntersection(other.storage)
}
func formSymmetricDifference(_ other: RefSet<Element>) {
storage.formSymmetricDifference(other.storage)
}
}
extension RefSet: Collection {
typealias Index = Set<Element>.Index
var startIndex: Index { return storage.startIndex }
var endIndex: Index { return storage.endIndex }
subscript(position: Index) -> Element {
return storage[position]
}
func index(after i: Index) -> Index {
return storage.index(after: i)
}
}