Get Dictionary Key with Same Hash Value

I'm building some data structures with specific behaviors for asynchronous access and modification. I've built out a Set-like 'register' where the register stores a set of unique, hashable, elements. I'd like to now build a Dictionary that has the same semantics, but uses the Set register internally.

The Set register uses a Dictionary internally, where the keys are the elements of the set and the values provide some metadata for other operations.

To use this Set register as a Dictionary, I created a Hashable Index struct that only hashes and compares key values. My thought being I could store this value in the internal Dictionary and retrieve the corresponding value stored in the index type.

My issue comes with actually retrieving that original key that I inserted into the dictionary. I've provided a high-level example of what I'm trying to do.

struct MapRegister<Key: Hashable, Value> {
    // This only hashes and equates using the `Key` value
    struct MapIndex: Hashable {
        let key: Key
        let value: Value?

        public static func == (_ lhs: MapIndex, _ rhs: MapIndex) -> Bool {
            lhs.key == rhs.key
        }

        func hash(into hasher: inout Hasher) {
            hasher.combine(key)
        }
    }

    var register: SetRegister<MapIndex>

    private func index(_ key: Key) -> MapIndex {
        MapIndex(key: key, value: nil)
    }

    subscript(_ key: Key) -> Value? {
        let index = index(key)
        // How can I retrieve the original key here?
        let key: MapIndex = register.elements[index]
        // So I can return the value here
        return key?.value
    }
}

struct SetRegister<Element: Hashable> {
    var elements: [Element: Metadata]
}

The SetRegister type has a mechanism for consistently overwriting a key and remembering it's new. So really, all I need is to efficiently retrieve the stored value using the hashed MapIndex.

Ideally I'd like to retain the O(n) lookup of a Dictionary, but I understand if that's not possible with this setup (I can always re-implement Set again for this but duplicating code like that seems a shame).

Not sure I got the intent of that code right, so take below with a grain of salt:

I'd start the other way around: with Dictionary being the base type. Set could be just a dictionary of Key -> Void.

And if to answer the subject line "literally": there could be many dictionary elements with the same hash value, so something is not quite right with an API that tries to get one (unless it is first / last kind of API).

2 Likes

Oh that's a good idea, I hadn't thought of that. I'll try it out and report back. Thanks!