Можно ли иметь один и тот же экземпляр коллекции в словаре, связанный с несколькими ключами в swift? - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть экземпляр 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 вместо Set Swift, но я хочу знать, как я могу подойти к этому, используя коллекции с семантикой значений, если это возможно.

1 Ответ

0 голосов
/ 27 апреля 2018

Ах! Теперь мы добрались до сути этого. Вам просто нужен ссылочный тип, основанный на stdlib, а не тот, который дает вам Foundation. Это легко реализовать, хотя и немного утомительно. Просто заверните набор в класс. Если вы не хотите полного соответствия 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)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...