| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- // Package mapx contains extra map types and functions.
- package mapx
- import (
- "iter"
- "slices"
- )
- // OrderedMap is a map that maintains the order of its keys.
- //
- // It is meant for maps that only grow or that are small;
- // is it not optimized for deleting keys.
- //
- // The zero value is ready to use.
- //
- // Locking-wise, it has the same rules as a regular Go map:
- // concurrent reads are safe, but not writes.
- type OrderedMap[K comparable, V any] struct {
- // m is the underlying map.
- m map[K]V
- // keys is the order of keys in the map.
- keys []K
- }
- func (m *OrderedMap[K, V]) init() {
- if m.m == nil {
- m.m = make(map[K]V)
- }
- }
- // Set sets the value for the given key in the map.
- //
- // If the key already exists, it updates the value and keeps the order.
- func (m *OrderedMap[K, V]) Set(key K, value V) {
- m.init()
- len0 := len(m.keys)
- m.m[key] = value
- if len(m.m) > len0 {
- // New key (not an update)
- m.keys = append(m.keys, key)
- }
- }
- // Get returns the value for the given key in the map.
- // If the key does not exist, it returns the zero value for V.
- func (m *OrderedMap[K, V]) Get(key K) V {
- return m.m[key]
- }
- // GetOk returns the value for the given key in the map
- // and whether it was present in the map.
- func (m *OrderedMap[K, V]) GetOk(key K) (_ V, ok bool) {
- v, ok := m.m[key]
- return v, ok
- }
- // Contains reports whether the map contains the given key.
- func (m *OrderedMap[K, V]) Contains(key K) bool {
- _, ok := m.m[key]
- return ok
- }
- // Delete removes the key from the map.
- //
- // The cost is O(n) in the number of keys in the map.
- func (m *OrderedMap[K, V]) Delete(key K) {
- len0 := len(m.m)
- delete(m.m, key)
- if len(m.m) == len0 {
- // Wasn't present; no need to adjust keys.
- return
- }
- was := m.keys
- m.keys = m.keys[:0]
- for _, k := range was {
- if k != key {
- m.keys = append(m.keys, k)
- }
- }
- }
- // All yields all the keys and values, in the order they were inserted.
- func (m *OrderedMap[K, V]) All() iter.Seq2[K, V] {
- return func(yield func(K, V) bool) {
- for _, k := range m.keys {
- if !yield(k, m.m[k]) {
- return
- }
- }
- }
- }
- // Keys yields the map keys, in the order they were inserted.
- func (m *OrderedMap[K, V]) Keys() iter.Seq[K] {
- return slices.Values(m.keys)
- }
- // Values yields the map values, in the order they were inserted.
- func (m *OrderedMap[K, V]) Values() iter.Seq[V] {
- return func(yield func(V) bool) {
- for _, k := range m.keys {
- if !yield(m.m[k]) {
- return
- }
- }
- }
- }
|