2023-09-23 13:39:05 +00:00
|
|
|
|
package collection
|
|
|
|
|
|
2024-03-03 08:06:29 +00:00
|
|
|
|
import (
|
|
|
|
|
"slices"
|
|
|
|
|
)
|
|
|
|
|
|
2023-09-23 13:39:05 +00:00
|
|
|
|
// Slice crée un slice générique contenant les valeurs d’entrée.
|
|
|
|
|
func Slice[T any](in ...T) (out []any) {
|
|
|
|
|
out = make([]any, len(in))
|
|
|
|
|
|
|
|
|
|
for i, e := range in {
|
|
|
|
|
out[i] = e
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add ajoute les valeurs d’entrée en fin du slice.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Add[T any, S ~[]T](s *S, in ...T) {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
*s = append(*s, in...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Insert ajoute les valeurs d’entrée en début du slice.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Insert[T any, S ~[]T](s *S, in ...T) {
|
|
|
|
|
*s = slices.Insert(*s, 0, in...)
|
2023-09-23 13:39:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InsertAt ajoute les valeurs d’entrée à l’index i du slice.
|
|
|
|
|
// - Si l’index est inférieur à 0, agit comme Insert.
|
|
|
|
|
// - Si l’index est supérieur ou égal à la taille du slice, agit comme Add.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func InsertAt[T any, S ~[]T](s *S, i int, in ...T) {
|
|
|
|
|
|
2023-09-23 13:39:05 +00:00
|
|
|
|
if i <= 0 {
|
|
|
|
|
Insert(s, in...)
|
|
|
|
|
} else if i >= len(*s) {
|
|
|
|
|
Add(s, in...)
|
2024-03-03 08:06:29 +00:00
|
|
|
|
} else {
|
|
|
|
|
*s = slices.Insert(*s, i, in...)
|
2023-09-23 13:39:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Diff retourne un slice contenant les entrées de s1 qui ne sont pas dans s2.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Diff[T comparable, S ~[]T](in1, in2 S) (out S) {
|
|
|
|
|
ss := NewSet(in2...)
|
2023-09-23 13:39:05 +00:00
|
|
|
|
|
2024-03-03 08:06:29 +00:00
|
|
|
|
for _, e := range in1 {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
if !ss.Contains(e) {
|
|
|
|
|
Add(&out, e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Intersect retourne un slice contenant les entrées contenues à la fois dans s1 et s2.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Intersect[T comparable, S ~[]T](in1, in2 S) (out S) {
|
|
|
|
|
ss := NewSet(in2...)
|
2023-09-23 13:39:05 +00:00
|
|
|
|
|
2024-03-03 08:06:29 +00:00
|
|
|
|
for _, e := range in1 {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
if ss.Contains(e) {
|
|
|
|
|
Add(&out, e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Uniq supprime les valeurs redondantes du slice.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Uniq[T comparable, S ~[]T](in S) (out S) {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
ss := NewSet[T]()
|
|
|
|
|
|
2024-03-03 08:06:29 +00:00
|
|
|
|
for _, e := range in {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
if !ss.Contains(e) {
|
|
|
|
|
ss.Add(e)
|
|
|
|
|
Add(&out, e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AddUniq ajoute les entrées en fin de slice si elles n’existent pas dans le slice.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func AddUniq[T comparable, S ~[]T](s *S, in ...T) {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
in2 := Uniq(Diff(in, *s))
|
|
|
|
|
Add(s, in2...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InsertUniq ajoute les entrées en début de slice si elles n’existent pas dans le slice.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func InsertUniq[T comparable, S ~[]T](s *S, in ...T) {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
in2 := Uniq(Diff(in, *s))
|
|
|
|
|
Insert(s, in2...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InsertAtUniq ajoute les entrées dans le slice à la position donnée si elles n’existent pas dans le slice.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func InsertAtUniq[T comparable, S ~[]T](s *S, i int, in ...T) {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
in2 := Uniq(Diff(in, *s))
|
|
|
|
|
InsertAt(s, i, in2...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Contains retourne vrai si le slice contient la valeur d’entrée.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Contains[T comparable, S ~[]T](s S, in T) bool {
|
|
|
|
|
return slices.Contains(s, in)
|
2023-09-23 13:39:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ContainsOneOf retourne vrai si le slice contient une des valeurs d’entrée.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func ContainsOneOf[T comparable, S ~[]T](s S, in ...T) bool {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
return NewSet(s...).ContainsOneOf(in...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ContainsAll retourne vrai si le slice contient toutes les valeurs d’entrée.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func ContainsAll[T comparable, S ~[]T](s S, in ...T) bool {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
return NewSet(s...).ContainsAll(in...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Maps retourne un slice à partir d’un autre slice en appliquant une fonction de transformation pour chaque valeur.
|
2024-03-04 08:20:42 +00:00
|
|
|
|
func Maps[T1, T2 any, S1 ~[]T1, S2 []T2](in S1, f func(T1) T2) (out S2) {
|
2024-03-03 08:06:29 +00:00
|
|
|
|
out = make(S2, len(in))
|
2023-09-23 13:39:05 +00:00
|
|
|
|
|
2024-03-03 08:06:29 +00:00
|
|
|
|
for i, e := range in {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
out[i] = f(e)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Filter retourne un nouveau slice dont les valeurs passent la fonction.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Filter[T any, S ~[]T](in S, f func(T) bool) (out S) {
|
|
|
|
|
for _, e := range in {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
if f(e) {
|
|
|
|
|
Add(&out, e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reduce applique une fonction à tous les éléments dont le résultat sert à la prochaine itération.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Reduce[T any, S ~[]T](in S, f func(T, T) T, initial ...T) (out T) {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
if len(initial) > 0 {
|
|
|
|
|
out = initial[0]
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-03 08:06:29 +00:00
|
|
|
|
for _, e := range in {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
out = f(out, e)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reverse inverse l’ordre du slice.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Reverse[T any, S ~[]T](in S) (out S) {
|
|
|
|
|
l := len(in)
|
|
|
|
|
out = make(S, l)
|
|
|
|
|
for i, e := range in {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
out[l-1-i] = e
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Zip retourne une map dont les clés sont les valeurs du premier slice et les valeurs, les valeurs du second.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Zip[K comparable, V any, SK ~[]K, SV ~[]V](keys SK, values SV) (out map[K]V) {
|
2023-09-23 13:39:05 +00:00
|
|
|
|
out = make(map[K]V)
|
2024-03-03 08:06:29 +00:00
|
|
|
|
l := min(len(keys), len(values))
|
2023-09-23 13:39:05 +00:00
|
|
|
|
|
2024-03-03 08:06:29 +00:00
|
|
|
|
for i, k := range keys[:l] {
|
|
|
|
|
out[k] = values[i]
|
2023-09-23 13:39:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unzip sépare les clés et les valeurs de la map en 2 slices distincts.
|
|
|
|
|
func Unzip[K comparable, V any](m map[K]V) (keys []K, values []V) {
|
|
|
|
|
for k, v := range m {
|
|
|
|
|
Add(&keys, k)
|
|
|
|
|
Add(&values, v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Equal retourne vrai si les slices sont identiques.
|
2024-03-03 08:06:29 +00:00
|
|
|
|
func Equal[T comparable, S ~[]T](s1, s2 S) bool {
|
|
|
|
|
return slices.Equal(s1, s2)
|
2023-09-23 13:39:05 +00:00
|
|
|
|
}
|