mirror of https://github.com/emirpasic/gods
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.0 KiB
Go
103 lines
3.0 KiB
Go
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package hashbidimap implements a bidirectional map backed by two hashmaps.
|
|
//
|
|
// A bidirectional map, or hash bag, is an associative data structure in which the (key,value) pairs form a one-to-one correspondence.
|
|
// Thus the binary relation is functional in each direction: value can also act as a key to key.
|
|
// A pair (a,b) thus provides a unique coupling between 'a' and 'b' so that 'b' can be found when 'a' is used as a key and 'a' can be found when 'b' is used as a key.
|
|
//
|
|
// Elements are unordered in the map.
|
|
//
|
|
// Structure is not thread safe.
|
|
//
|
|
// Reference: https://en.wikipedia.org/wiki/Bidirectional_map
|
|
package hashbidimap
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/emirpasic/gods/v2/maps"
|
|
"github.com/emirpasic/gods/v2/maps/hashmap"
|
|
)
|
|
|
|
// Assert Map implementation
|
|
var _ maps.BidiMap[string, int] = (*Map[string, int])(nil)
|
|
|
|
// Map holds the elements in two hashmaps.
|
|
type Map[K, V comparable] struct {
|
|
forwardMap hashmap.Map[K, V]
|
|
inverseMap hashmap.Map[V, K]
|
|
}
|
|
|
|
// New instantiates a bidirectional map.
|
|
func New[K, V comparable]() *Map[K, V] {
|
|
return &Map[K, V]{*hashmap.New[K, V](), *hashmap.New[V, K]()}
|
|
}
|
|
|
|
// Put inserts element into the map.
|
|
func (m *Map[K, V]) Put(key K, value V) {
|
|
if valueByKey, ok := m.forwardMap.Get(key); ok {
|
|
m.inverseMap.Remove(valueByKey)
|
|
}
|
|
if keyByValue, ok := m.inverseMap.Get(value); ok {
|
|
m.forwardMap.Remove(keyByValue)
|
|
}
|
|
m.forwardMap.Put(key, value)
|
|
m.inverseMap.Put(value, key)
|
|
}
|
|
|
|
// Get searches the element in the map by key and returns its value or nil if key is not found in map.
|
|
// Second return parameter is true if key was found, otherwise false.
|
|
func (m *Map[K, V]) Get(key K) (value V, found bool) {
|
|
return m.forwardMap.Get(key)
|
|
}
|
|
|
|
// GetKey searches the element in the map by value and returns its key or nil if value is not found in map.
|
|
// Second return parameter is true if value was found, otherwise false.
|
|
func (m *Map[K, V]) GetKey(value V) (key K, found bool) {
|
|
return m.inverseMap.Get(value)
|
|
}
|
|
|
|
// Remove removes the element from the map by key.
|
|
func (m *Map[K, V]) Remove(key K) {
|
|
if value, found := m.forwardMap.Get(key); found {
|
|
m.forwardMap.Remove(key)
|
|
m.inverseMap.Remove(value)
|
|
}
|
|
}
|
|
|
|
// Empty returns true if map does not contain any elements
|
|
func (m *Map[K, V]) Empty() bool {
|
|
return m.Size() == 0
|
|
}
|
|
|
|
// Size returns number of elements in the map.
|
|
func (m *Map[K, V]) Size() int {
|
|
return m.forwardMap.Size()
|
|
}
|
|
|
|
// Keys returns all keys (random order).
|
|
func (m *Map[K, V]) Keys() []K {
|
|
return m.forwardMap.Keys()
|
|
}
|
|
|
|
// Values returns all values (random order).
|
|
func (m *Map[K, V]) Values() []V {
|
|
return m.inverseMap.Keys()
|
|
}
|
|
|
|
// Clear removes all elements from the map.
|
|
func (m *Map[K, V]) Clear() {
|
|
m.forwardMap.Clear()
|
|
m.inverseMap.Clear()
|
|
}
|
|
|
|
// String returns a string representation of container
|
|
func (m *Map[K, V]) String() string {
|
|
str := "HashBidiMap\n"
|
|
str += fmt.Sprintf("%v", m.forwardMap)
|
|
return str
|
|
}
|