mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-06-09 07:53:58 +02:00
07c8adaf76
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
231 lines
5.6 KiB
Go
231 lines
5.6 KiB
Go
package g
|
||
|
||
import (
|
||
"fmt"
|
||
"maps"
|
||
|
||
"github.com/enetx/g/f"
|
||
"github.com/enetx/iter"
|
||
)
|
||
|
||
// NewMap creates a new Map of the specified size or an empty Map if no size is provided.
|
||
func NewMap[K comparable, V any](size ...Int) Map[K, V] {
|
||
return make(Map[K, V], Slice[Int](size).Get(0).UnwrapOrDefault())
|
||
}
|
||
|
||
// Transform applies a transformation function to the Map and returns the result.
|
||
func (m Map[K, V]) Transform(fn func(Map[K, V]) Map[K, V]) Map[K, V] { return fn(m) }
|
||
|
||
// Entry returns an MapEntry object for the given key, providing fine‑grained
|
||
// control over insertion and modification of its value.
|
||
//
|
||
// Example:
|
||
//
|
||
// m := g.NewMap[string, int]()
|
||
// // Insert 1 if "foo" is absent, then increment it
|
||
// e := m.Entry("foo")
|
||
// e.OrSet(1)
|
||
// e.Transform(func(v int) int { return v + 1 })
|
||
//
|
||
// The entire operation requires only a single key lookup and works without
|
||
// additional allocations.
|
||
func (m Map[K, V]) Entry(key K) MapEntry[K, V] { return MapEntry[K, V]{m, key} }
|
||
|
||
// Iter returns an iterator (SeqMap[K, V]) for the Map, allowing for sequential iteration
|
||
// over its key-value pairs. It is commonly used in combination with higher-order functions,
|
||
// such as 'ForEach', to perform operations on each key-value pair of the Map.
|
||
//
|
||
// Returns:
|
||
//
|
||
// - SeqMap[K, V], which can be used for sequential iteration over the key-value pairs of the Map.
|
||
//
|
||
// Example usage:
|
||
//
|
||
// myMap := g.Map[string, int]{"one": 1, "two": 2, "three": 3}
|
||
// iterator := myMap.Iter()
|
||
// iterator.ForEach(func(key string, value int) {
|
||
// // Perform some operation on each key-value pair
|
||
// fmt.Printf("%s: %d\n", key, value)
|
||
// })
|
||
//
|
||
// The 'Iter' method provides a convenient way to traverse the key-value pairs of a Map
|
||
// in a functional style, enabling operations like mapping or filtering.
|
||
func (m Map[K, V]) Iter() SeqMap[K, V] { return SeqMap[K, V](iter.FromMap(m)) }
|
||
|
||
// Invert inverts the keys and values of the Map, returning a new Map with values as keys and
|
||
// keys as values. Note that the inverted Map will have 'any' as the key type, since not all value
|
||
// types are guaranteed to be comparable.
|
||
func (m Map[K, V]) Invert() Map[any, K] {
|
||
if m.Empty() {
|
||
return NewMap[any, K]()
|
||
}
|
||
|
||
result := make(Map[any, K], len(m))
|
||
for k, v := range m {
|
||
result[v] = k
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// Keys returns a slice of the Map's keys.
|
||
func (m Map[K, V]) Keys() Slice[K] {
|
||
if m.Empty() {
|
||
return NewSlice[K]()
|
||
}
|
||
|
||
keys := make(Slice[K], 0, len(m))
|
||
for k := range m {
|
||
keys = append(keys, k)
|
||
}
|
||
|
||
return keys
|
||
}
|
||
|
||
// Values returns a slice of the Map's values.
|
||
func (m Map[K, V]) Values() Slice[V] {
|
||
if m.Empty() {
|
||
return NewSlice[V]()
|
||
}
|
||
|
||
values := make(Slice[V], 0, len(m))
|
||
for _, v := range m {
|
||
values = append(values, v)
|
||
}
|
||
|
||
return values
|
||
}
|
||
|
||
// Contains checks if the Map contains the specified key.
|
||
func (m Map[K, V]) Contains(key K) bool {
|
||
_, ok := m[key]
|
||
return ok
|
||
}
|
||
|
||
// Clone creates a new Map that is a copy of the original Map.
|
||
func (m Map[K, V]) Clone() Map[K, V] { return maps.Clone(m) }
|
||
|
||
// Copy copies the source Map's key-value pairs to the target Map.
|
||
func (m Map[K, V]) Copy(src Map[K, V]) { maps.Copy(m, src) }
|
||
|
||
// Delete removes the specified keys from the Map.
|
||
func (m Map[K, V]) Delete(keys ...K) {
|
||
for _, key := range keys {
|
||
delete(m, key)
|
||
}
|
||
}
|
||
|
||
// Std converts the Map to a regular Go map.
|
||
func (m Map[K, V]) Std() map[K]V { return m }
|
||
|
||
// ToMapOrd converts a standard Map to an ordered Map.
|
||
func (m Map[K, V]) ToMapOrd() MapOrd[K, V] {
|
||
mo := NewMapOrd[K, V](m.Len())
|
||
for k, v := range m {
|
||
mo.Set(k, v)
|
||
}
|
||
|
||
return mo
|
||
}
|
||
|
||
// ToMapSafe converts a standard Map to a thread-safe Map.
|
||
func (m Map[K, V]) ToMapSafe() *MapSafe[K, V] {
|
||
ms := NewMapSafe[K, V]()
|
||
for k, v := range m {
|
||
ms.Set(k, v)
|
||
}
|
||
|
||
return ms
|
||
}
|
||
|
||
// Eq checks if two Maps are equal.
|
||
func (m Map[K, V]) Eq(other Map[K, V]) bool {
|
||
n := len(m)
|
||
if n != len(other) {
|
||
return false
|
||
}
|
||
|
||
if n == 0 {
|
||
return true
|
||
}
|
||
|
||
var zero V
|
||
comparable := f.IsComparable(zero)
|
||
|
||
for k, value := range m {
|
||
ovalue, ok := other[k]
|
||
if !ok || comparable && !f.Eq[any](value)(ovalue) || !comparable && !f.Eqd(value)(ovalue) {
|
||
return false
|
||
}
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
// String returns a string representation of the Map.
|
||
func (m Map[K, V]) String() string {
|
||
if len(m) == 0 {
|
||
return "Map{}"
|
||
}
|
||
|
||
var b Builder
|
||
b.WriteString("Map{")
|
||
|
||
first := true
|
||
for k, v := range m {
|
||
if !first {
|
||
b.WriteString(", ")
|
||
}
|
||
|
||
first = false
|
||
b.WriteString(Format("{}:{}", k, v))
|
||
}
|
||
|
||
b.WriteString("}")
|
||
|
||
return b.String().Std()
|
||
}
|
||
|
||
// Clear removes all key-value pairs from the Map.
|
||
func (m Map[K, V]) Clear() { clear(m) }
|
||
|
||
// Empty checks if the Map is empty.
|
||
func (m Map[K, V]) Empty() bool { return len(m) == 0 }
|
||
|
||
// Get retrieves the value associated with the given key.
|
||
func (m Map[K, V]) Get(k K) Option[V] {
|
||
if v, ok := m[k]; ok {
|
||
return Some(v)
|
||
}
|
||
|
||
return None[V]()
|
||
}
|
||
|
||
// Len returns the number of key-value pairs in the Map.
|
||
func (m Map[K, V]) Len() Int { return Int(len(m)) }
|
||
|
||
// Ne checks if two Maps are not equal.
|
||
func (m Map[K, V]) Ne(other Map[K, V]) bool { return !m.Eq(other) }
|
||
|
||
// NotEmpty checks if the Map is not empty.
|
||
func (m Map[K, V]) NotEmpty() bool { return !m.Empty() }
|
||
|
||
// Set sets the value for the key and returns the previous value if it existed.
|
||
func (m Map[K, V]) Set(key K, value V) Option[V] {
|
||
prev, ok := m[key]
|
||
m[key] = value
|
||
if ok {
|
||
return Some(prev)
|
||
}
|
||
|
||
return None[V]()
|
||
}
|
||
|
||
// Print writes the key-value pairs of the Map to the standard output (console)
|
||
// and returns the Map unchanged.
|
||
func (m Map[K, V]) Print() Map[K, V] { fmt.Print(m); return m }
|
||
|
||
// Println writes the key-value pairs of the Map to the standard output (console) with a newline
|
||
// and returns the Map unchanged.
|
||
func (m Map[K, V]) Println() Map[K, V] { fmt.Println(m); return m }
|