File: slice.go

package info (click to toggle)
golang-github-charmbracelet-x 0.0~git20251028.0cf22f8%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,940 kB
  • sloc: sh: 124; makefile: 5
file content (137 lines) | stat: -rw-r--r-- 3,532 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Package slice provides utility functions for working with slices in Go.
package slice

import (
	"slices"
)

// GroupBy groups a slice of items by a key function.
func GroupBy[T any, K comparable](list []T, key func(T) K) map[K][]T {
	groups := make(map[K][]T)

	for _, item := range list {
		k := key(item)
		groups[k] = append(groups[k], item)
	}

	return groups
}

// Take returns the first n elements of the given slice. If there are not
// enough elements in the slice, the whole slice is returned.
func Take[A any](slice []A, n int) []A {
	if n > len(slice) {
		return slice
	}
	return slice[:n]
}

// Last returns the last element of a slice and true. If the slice is empty, it
// returns the zero value and false.
func Last[T any](list []T) (T, bool) {
	if len(list) == 0 {
		var zero T
		return zero, false
	}
	return list[len(list)-1], true
}

// Uniq returns a new slice with all duplicates removed.
func Uniq[T comparable](list []T) []T {
	seen := make(map[T]struct{}, len(list))
	uniqList := make([]T, 0, len(list))

	for _, item := range list {
		if _, ok := seen[item]; !ok {
			seen[item] = struct{}{}
			uniqList = append(uniqList, item)
		}
	}

	return uniqList
}

// Intersperse puts an item between each element of a slice, returning a new
// slice.
func Intersperse[T any](slice []T, insert T) []T {
	if len(slice) <= 1 {
		return slice
	}

	// Create a new slice with the required capacity.
	result := make([]T, len(slice)*2-1)

	for i := range slice {
		// Fill the new slice with original elements and the insertion string.
		result[i*2] = slice[i]

		// Add the insertion string between items (except the last one).
		if i < len(slice)-1 {
			result[i*2+1] = insert
		}
	}

	return result
}

// ContainsAny checks if any of the given values present in the list.
func ContainsAny[T comparable](list []T, values ...T) bool {
	return slices.ContainsFunc(list, func(v T) bool {
		return slices.Contains(values, v)
	})
}

// Shift removes and returns the first element of a slice.
// It returns the removed element and the modified slice.
// The third return value (ok) indicates whether an element was removed.
func Shift[T any](slice []T) (element T, newSlice []T, ok bool) {
	if len(slice) == 0 {
		var zero T
		return zero, slice, false
	}
	return slice[0], slice[1:], true
}

// Pop removes and returns the last element of a slice.
// It returns the removed element and the modified slice.
// The third return value (ok) indicates whether an element was removed.
func Pop[T any](slice []T) (element T, newSlice []T, ok bool) {
	if len(slice) == 0 {
		var zero T
		return zero, slice, false
	}
	lastIdx := len(slice) - 1
	return slice[lastIdx], slice[:lastIdx], true
}

// DeleteAt removes and returns the element at the specified index.
// It returns the removed element and the modified slice.
// The third return value (ok) indicates whether an element was removed.
func DeleteAt[T any](slice []T, index int) (element T, newSlice []T, ok bool) {
	if index < 0 || index >= len(slice) {
		var zero T
		return zero, slice, false
	}

	element = slice[index]
	newSlice = slices.Delete(slices.Clone(slice), index, index+1)

	return element, newSlice, true
}

// IsSubset checks if all elements of slice a are present in slice b.
func IsSubset[T comparable](a, b []T) bool {
	if len(a) > len(b) {
		return false
	}
	set := make(map[T]struct{}, len(b))
	for _, item := range b {
		set[item] = struct{}{}
	}
	for _, item := range a {
		if _, exists := set[item]; !exists {
			return false
		}
	}
	return true
}