122 lines
3.2 KiB
Go
122 lines
3.2 KiB
Go
/*
|
|
* Copyright 2024 CloudWeGo Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package gmap
|
|
|
|
// Concat returns the unions of maps as a new map.
|
|
//
|
|
// 💡 NOTE:
|
|
//
|
|
// - Once the key conflicts, the newer value always replace the older one ([DiscardOld]),
|
|
// - If the result is an empty set, always return an empty map instead of nil
|
|
//
|
|
// 🚀 EXAMPLE:
|
|
//
|
|
// m := map[int]int{1: 1, 2: 2}
|
|
// Concat(m, nil) ⏩ map[int]int{1: 1, 2: 2}
|
|
// Concat(m, map[int]{3: 3}) ⏩ map[int]int{1: 1, 2: 2, 3: 3}
|
|
// Concat(m, map[int]{2: -1}) ⏩ map[int]int{1: 1, 2: -1} // "2:2" is replaced by the newer "2:-1"
|
|
//
|
|
// 💡 AKA: Merge, Union, Combine
|
|
func Concat[K comparable, V any](ms ...map[K]V) map[K]V {
|
|
// FastPath: no map or only one map given.
|
|
if len(ms) == 0 {
|
|
return make(map[K]V)
|
|
}
|
|
if len(ms) == 1 {
|
|
return cloneWithoutNilCheck(ms[0])
|
|
}
|
|
|
|
var maxLen int
|
|
for _, m := range ms {
|
|
if len(m) > maxLen {
|
|
maxLen = len(m)
|
|
}
|
|
}
|
|
ret := make(map[K]V, maxLen)
|
|
// FastPath: all maps are empty.
|
|
if maxLen == 0 {
|
|
return ret
|
|
}
|
|
|
|
// Concat all maps.
|
|
for _, m := range ms {
|
|
for k, v := range m {
|
|
ret[k] = v
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// Map applies function f to each key and value of map m.
|
|
// Results of f are returned as a new map.
|
|
//
|
|
// 🚀 EXAMPLE:
|
|
//
|
|
// f := func(k, v int) (string, string) { return strconv.Itoa(k), strconv.Itoa(v) }
|
|
// Map(map[int]int{1: 1}, f) ⏩ map[string]string{"1": "1"}
|
|
// Map(map[int]int{}, f) ⏩ map[string]string{}
|
|
func Map[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2)) map[K2]V2 {
|
|
r := make(map[K2]V2, len(m))
|
|
for k, v := range m {
|
|
k2, v2 := f(k, v)
|
|
r[k2] = v2
|
|
}
|
|
return r
|
|
}
|
|
|
|
// Values returns the values of the map m.
|
|
//
|
|
// 🚀 EXAMPLE:
|
|
//
|
|
// m := map[int]string{1: "1", 2: "2", 3: "3", 4: "4"}
|
|
// Values(m) ⏩ []string{"1", "4", "2", "3"} //⚠️INDETERMINATE ORDER⚠️
|
|
//
|
|
// ⚠️ WARNING: The keys values be in an indeterminate order,
|
|
func Values[K comparable, V any](m map[K]V) []V {
|
|
r := make([]V, 0, len(m))
|
|
for _, v := range m {
|
|
r = append(r, v)
|
|
}
|
|
return r
|
|
}
|
|
|
|
// Clone returns a shallow copy of map.
|
|
// If the given map is nil, nil is returned.
|
|
//
|
|
// 🚀 EXAMPLE:
|
|
//
|
|
// Clone(map[int]int{1: 1, 2: 2}) ⏩ map[int]int{1: 1, 2: 2}
|
|
// Clone(map[int]int{}) ⏩ map[int]int{}
|
|
// Clone[int, int](nil) ⏩ nil
|
|
//
|
|
// 💡 HINT: Both keys and values are copied using assignment (=), so this is a shallow clone.
|
|
// 💡 AKA: Copy
|
|
func Clone[K comparable, V any, M ~map[K]V](m M) M {
|
|
if m == nil {
|
|
return nil
|
|
}
|
|
return cloneWithoutNilCheck(m)
|
|
}
|
|
|
|
func cloneWithoutNilCheck[K comparable, V any, M ~map[K]V](m M) M {
|
|
r := make(M, len(m))
|
|
for k, v := range m {
|
|
r[k] = v
|
|
}
|
|
return r
|
|
}
|