-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit bc4c026
Showing
8 changed files
with
999 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
|
||
# Created by https://www.toptal.com/developers/gitignore/api/go | ||
# Edit at https://www.toptal.com/developers/gitignore?templates=go | ||
|
||
### Go ### | ||
# If you prefer the allow list template instead of the deny list, see community template: | ||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore | ||
# | ||
# Binaries for programs and plugins | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
|
||
# Test binary, built with `go test -c` | ||
*.test | ||
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
|
||
# Dependency directories (remove the comment below to include it) | ||
# vendor/ | ||
|
||
# Go workspace file | ||
go.work | ||
|
||
### Go Patch ### | ||
/vendor/ | ||
/Godeps/ | ||
|
||
# End of https://www.toptal.com/developers/gitignore/api/go | ||
|
||
cover.out | ||
cover.html | ||
.vscode | ||
|
||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2023 Samuel Berthe | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
|
||
BIN=go | ||
|
||
build: | ||
${BIN} build -v ./... | ||
|
||
test: | ||
go test -race -v ./... | ||
watch-test: | ||
reflex -t 50ms -s -- sh -c 'gotest -race -v ./...' | ||
|
||
bench: | ||
go test -benchmem -count 3 -bench ./... | ||
watch-bench: | ||
reflex -t 50ms -s -- sh -c 'go test -benchmem -count 3 -bench ./...' | ||
|
||
coverage: | ||
${BIN} test -v -coverprofile=cover.out -covermode=atomic . | ||
${BIN} tool cover -html=cover.out -o cover.html | ||
|
||
tools: | ||
${BIN} install github.com/cespare/reflex@latest | ||
${BIN} install github.com/rakyll/gotest@latest | ||
${BIN} install github.com/psampaz/go-mod-outdated@latest | ||
${BIN} install github.com/jondot/goweight@latest | ||
${BIN} install github.com/golangci/golangci-lint/cmd/golangci-lint@latest | ||
${BIN} get -t -u golang.org/x/tools/cmd/cover | ||
${BIN} install github.com/sonatype-nexus-community/nancy@latest | ||
go mod tidy | ||
|
||
lint: | ||
golangci-lint run --timeout 60s --max-same-issues 50 ./... | ||
lint-fix: | ||
golangci-lint run --timeout 60s --max-same-issues 50 --fix ./... | ||
|
||
audit: | ||
${BIN} list -json -m all | nancy sleuth | ||
|
||
outdated: | ||
${BIN} list -u -m -json all | go-mod-outdated -update -direct | ||
|
||
weight: | ||
goweight |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
// Package genericlist provides a versatile and type-safe generic list for any type | ||
// that implements the 'comparable' contract, which allows for comparisons using | ||
// the standard comparison operators (<, >, ==, etc.). | ||
package genericlist | ||
|
||
// GenericList represents a type-safe, dynamic list of comparable items. | ||
type GenericList[T comparable] struct { | ||
data []T | ||
} | ||
|
||
// New initializes an empty list. | ||
func (g *GenericList[T]) New() { | ||
g.data = []T{} | ||
} | ||
|
||
// Add appends the provided value to the end of the list. | ||
func (g *GenericList[T]) Add(value T) { | ||
g.data = append(g.data, value) | ||
} | ||
|
||
// Remove deletes the element at the specified index from the list. | ||
// Panics if the index is out of bounds. | ||
func (g *GenericList[T]) Remove(i int) { | ||
if i < 0 || i > len(g.data)-1 { | ||
panic("index is out of range") | ||
} | ||
g.data = append(g.data[:i], g.data[i+1:]...) | ||
} | ||
|
||
// RemoveByValue deletes the first occurrence of the specified value from the list. | ||
// Panics if the value is uninitialized. | ||
func (g *GenericList[T]) RemoveByValue(value T) { | ||
if value == *new(T) { | ||
panic("value is nil") | ||
} | ||
for i := 0; i < len(g.data); i++ { | ||
if g.data[i] == value { | ||
g.Remove(i) | ||
return | ||
} | ||
} | ||
} | ||
|
||
// Clear erases all elements from the list, resetting it to empty. | ||
func (g *GenericList[T]) Clear() { | ||
g.data = []T{} | ||
} | ||
|
||
// Count returns the number of elements currently in the list. | ||
func (g *GenericList[T]) Count() int { | ||
return len(g.data) | ||
} | ||
|
||
// Clone creates and returns a new list with elements identical to the current list. | ||
func (g *GenericList[T]) Clone() *GenericList[T] { | ||
return &GenericList[T]{data: g.data} | ||
} | ||
|
||
// Merge appends all elements from the provided list to the current list. | ||
func (g *GenericList[T]) Merge(list *GenericList[T]) { | ||
if list == nil { | ||
panic("list is nil") | ||
} | ||
g.data = append(g.data, list.data...) | ||
} | ||
|
||
// Get retrieves the element at the specified index from the list. | ||
func (g *GenericList[T]) Get(i int) T { | ||
if i < 0 || i > len(g.data)-1 { | ||
panic("index is out of range") | ||
} | ||
return g.data[i] | ||
} | ||
|
||
// IndexOf finds and returns the index of the first occurrence of the provided value. | ||
// Returns -1 if the value is not found in the list. | ||
func (g *GenericList[T]) IndexOf(value T) int { | ||
if value == *new(T) { | ||
panic("value is nil") | ||
} | ||
for i := 0; i < len(g.data); i++ { | ||
if g.data[i] == value { | ||
return i | ||
} | ||
} | ||
return -1 | ||
} | ||
|
||
// Contains checks if the list contains the provided value. | ||
func (g *GenericList[T]) Contains(value T) bool { | ||
if value == *new(T) { | ||
panic("value is nil") | ||
} | ||
for i := 0; i < len(g.data); i++ { | ||
if g.data[i] == value { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
// ForEach executes the provided function for each element in the list. | ||
func (g *GenericList[T]) ForEach(f func(*T)) { | ||
for i := range g.data { | ||
f(&g.data[i]) | ||
} | ||
} | ||
|
||
// Map produces a new list by applying the provided function to each element of the current list. | ||
func (g *GenericList[T]) Map(f func(T) T) *GenericList[T] { | ||
result := GenericList[T]{} | ||
for _, item := range g.data { | ||
result.Add(f(item)) | ||
} | ||
return &result | ||
} | ||
|
||
// Filter creates a new list containing only elements for which the provided function returns true. | ||
func (g *GenericList[T]) Filter(f func(T) bool) *GenericList[T] { | ||
result := GenericList[T]{} | ||
for _, item := range g.data { | ||
if f(item) { | ||
result.Add(item) | ||
} | ||
} | ||
return &result | ||
} | ||
|
||
// Reduce reduces the list to a single value using the provided function. | ||
// Starts with the first element as the initial accumulator and applies the function for each subsequent element. | ||
func (g *GenericList[T]) Reduce(f func(T, T) T) T { | ||
if len(g.data) == 0 { | ||
return *new(T) | ||
} | ||
acc := g.data[0] | ||
for _, item := range g.data[1:] { | ||
acc = f(acc, item) | ||
} | ||
return acc | ||
} | ||
|
||
// Any checks if any element in the list satisfies the condition in the provided function. | ||
func (g *GenericList[T]) Any(f func(T) bool) bool { | ||
for _, item := range g.data { | ||
if f(item) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
// All verifies if all elements in the list satisfy the condition in the provided function. | ||
func (g *GenericList[T]) All(f func(T) bool) bool { | ||
for _, item := range g.data { | ||
if !f(item) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
// Reverse reverses the order of elements in the list. | ||
func (g *GenericList[T]) Reverse() { | ||
for i := 0; i < len(g.data)/2; i++ { | ||
g.data[i], g.data[len(g.data)-i-1] = g.data[len(g.data)-i-1], g.data[i] | ||
} | ||
} | ||
|
||
// Swap exchanges positions of elements at the specified indices in the list. | ||
func (g *GenericList[T]) Swap(i, j int) { | ||
if i < 0 || i > len(g.data)-1 || j < 0 || j > len(g.data)-1 { | ||
panic("index is out of range") | ||
} | ||
g.data[i], g.data[j] = g.data[j], g.data[i] | ||
} | ||
|
||
// IsEmpty checks if the list is currently empty. | ||
func (g *GenericList[T]) IsEmpty() bool { | ||
return len(g.data) == 0 | ||
} | ||
|
||
// IsNotEmpty checks if the list contains any elements. | ||
func (g *GenericList[T]) IsNotEmpty() bool { | ||
return len(g.data) > 0 | ||
} | ||
|
||
// First retrieves the first element of the list. | ||
func (g *GenericList[T]) First() T { | ||
if g.IsEmpty() { | ||
return *new(T) | ||
} | ||
return g.data[0] | ||
} | ||
|
||
// Last fetches the last element of the list. | ||
func (g *GenericList[T]) Last() T { | ||
if g.IsEmpty() { | ||
return *new(T) | ||
} | ||
return g.data[len(g.data)-1] | ||
} | ||
|
||
// ToSlice converts the list to a standard Go slice. | ||
func (g *GenericList[T]) ToSlice() []T { | ||
return g.data | ||
} | ||
|
||
// FromSlice initializes the list with the elements from the provided slice. | ||
func (g *GenericList[T]) FromSlice(data []T) { | ||
g.data = data | ||
} | ||
|
||
// CopyFromSlice replaces the current list with a deep copy of the provided slice. | ||
func (g *GenericList[T]) CopyFromSlice(data []T) { | ||
g.data = append([]T{}, data...) | ||
} | ||
|
||
// CopyTo copies the elements of the current list (g) into the provided list. | ||
// The provided list's data will be replaced by the elements from the current list. | ||
// Panics if the provided list is nil. | ||
func (g *GenericList[T]) CopyTo(list *GenericList[T]) { | ||
if list == nil { | ||
panic("list is nil") | ||
} | ||
|
||
// Create a slice with the same length and capacity as g.data | ||
list.data = make([]T, len(g.data)) | ||
|
||
copy(list.data, g.data) | ||
} | ||
|
||
// CopyToSlice copies the list to the given slice | ||
func (g *GenericList[T]) CopyToSlice(data []T) { | ||
copy(data, g.data) | ||
} | ||
|
||
// Copy creates a new list with elements identical to the current list. | ||
func (g *GenericList[T]) Copy() *GenericList[T] { | ||
return &GenericList[T]{data: g.data} | ||
} | ||
|
||
// CopyFrom replaces the current list's (g) data with the elements from the provided list. | ||
// The current list's data will be overwritten with the data from the provided list. | ||
// Panics if the provided list is nil. | ||
func (g *GenericList[T]) CopyFrom(list *GenericList[T]) { | ||
if list == nil { | ||
panic("list is nil") | ||
} | ||
g.data = make([]T, len(list.data)) | ||
copy(g.data, list.data) | ||
} |
Oops, something went wrong.