package collection // 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. func Add[T any](s *([]T), in ...T) { *s = append(*s, in...) } // Insert ajoute les valeurs d’entrée en début du slice. func Insert[T any](s *([]T), in ...T) { *s = append(in, (*s)...) } // 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. func InsertAt[T any](s *([]T), i int, in ...T) { if i <= 0 { Insert(s, in...) return } else if i >= len(*s) { Add(s, in...) return } l1, l2 := len(*s), len(in) result := make([]T, l1+l2) copy(result[:i], (*s)[:i]) copy(result[i:i+l2], in) copy(result[i+l2:], (*s)[i:]) *s = result } // Diff retourne un slice contenant les entrées de s1 qui ne sont pas dans s2. func Diff[T comparable](s1, s2 []T) (out []T) { ss := NewSet(s2...) for _, e := range s1 { if !ss.Contains(e) { Add(&out, e) } } return } // Intersect retourne un slice contenant les entrées contenues à la fois dans s1 et s2. func Intersect[T comparable](s1, s2 []T) (out []T) { ss := NewSet(s2...) for _, e := range s1 { if ss.Contains(e) { Add(&out, e) } } return } // Uniq supprime les valeurs redondantes du slice. func Uniq[T comparable](s []T) (out []T) { ss := NewSet[T]() for _, e := range s { 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. func AddUniq[T comparable](s *([]T), in ...T) { 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. func InsertUniq[T comparable](s *([]T), in ...T) { 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. func InsertAtUniq[T comparable](s *([]T), i int, in ...T) { in2 := Uniq(Diff(in, *s)) InsertAt(s, i, in2...) } // Contains retourne vrai si le slice contient la valeur d’entrée. func Contains[T comparable](s []T, in T) bool { for _, e := range s { if e == in { return true } } return false } // ContainsOneOf retourne vrai si le slice contient une des valeurs d’entrée. func ContainsOneOf[T comparable](s []T, in ...T) bool { return NewSet(s...).ContainsOneOf(in...) } // ContainsAll retourne vrai si le slice contient toutes les valeurs d’entrée. func ContainsAll[T comparable](s []T, in ...T) bool { return NewSet(s...).ContainsAll(in...) } // Maps retourne un slice à partir d’un autre slice en appliquant une fonction de transformation pour chaque valeur. func Maps[T1, T2 any](s []T1, f func(T1) T2) (out []T2) { out = make([]T2, len(s)) for i, e := range s { out[i] = f(e) } return } // Filter retourne un nouveau slice dont les valeurs passent la fonction. func Filter[T any](s []T, f func(T) bool) (out []T) { for _, e := range s { if f(e) { Add(&out, e) } } return } // Reduce applique une fonction à tous les éléments dont le résultat sert à la prochaine itération. func Reduce[T any](s []T, f func(T, T) T, initial ...T) (out T) { if len(initial) > 0 { out = initial[0] } for _, e := range s { out = f(out, e) } return } // Reverse inverse l’ordre du slice. func Reverse[T any](s []T) (out []T) { l := len(s) out = make([]T, l) for i, e := range s { 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. func Zip[K comparable, V any](s1 []K, s2 []V) (out map[K]V) { out = make(map[K]V) l := min(len(s1), len(s2)) for i, k := range s1[:l] { out[k] = s2[i] } 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. func Equal[T comparable](sl1, sl2 []T) bool { if len(sl1) != len(sl2) { return false } for i, e1 := range sl1 { if e1 != sl2[i] { return false } } return true }