├── .github └── workflows │ ├── bench.yml │ ├── go.yml │ └── release.yml ├── .gitignore ├── .golangci.yml ├── LICENSE ├── README.md ├── benchmark.txt ├── containers ├── containers.go ├── containers_test.go ├── enumerable.go ├── iterator.go └── serialization.go ├── examples ├── README.md ├── arraylist │ └── arraylist.go ├── arraystack │ └── arraystack.go ├── avltree │ └── avltree.go ├── binaryheap │ └── binaryheap.go ├── btree │ └── btree.go ├── customcomparator │ └── customcomparator.go ├── doublylinkedlist │ └── doublylinkedlist.go ├── enumerablewithindex │ └── enumerablewithindex.go ├── enumerablewithkey │ └── enumerablewithkey.go ├── godsort │ └── godsort.go ├── hashbidimap │ └── hashbidimap.go ├── hashmap │ └── hashmap.go ├── hashset │ └── hashset.go ├── iteratorwithindex │ └── iteratorwithindex.go ├── iteratorwithkey │ └── iteratorwithkey.go ├── linkedhashmap │ └── linkedhashmap.go ├── linkedhashset │ └── linkedhashset.go ├── linkedliststack │ └── linkedliststack.go ├── redblacktree │ └── redblacktree.go ├── redblacktreeextended │ └── redblacktreeextended.go ├── serialization │ └── serialization.go ├── singlylinkedlist │ └── singlylinkedlist.go ├── treebidimap │ └── treebidimap.go ├── treemap │ └── treemap.go └── treeset │ └── treeset.go ├── go.mod ├── go.sum ├── lists ├── arraylist │ ├── arraylist.go │ ├── arraylist_test.go │ ├── enumerable.go │ ├── iterator.go │ └── serialization.go ├── doublylinkedlist │ ├── doublylinkedlist.go │ ├── doublylinkedlist_test.go │ ├── enumerable.go │ ├── iterator.go │ └── serialization.go ├── lists.go └── singlylinkedlist │ ├── enumerable.go │ ├── iterator.go │ ├── serialization.go │ ├── singlylinkedlist.go │ └── singlylinkedlist_test.go ├── maps ├── hashbidimap │ ├── hashbidimap.go │ ├── hashbidimap_test.go │ └── serialization.go ├── hashmap │ ├── hashmap.go │ ├── hashmap_test.go │ └── serialization.go ├── linkedhashmap │ ├── enumerable.go │ ├── iterator.go │ ├── linkedhashmap.go │ ├── linkedhashmap_test.go │ └── serialization.go ├── maps.go ├── treebidimap │ ├── enumerable.go │ ├── iterator.go │ ├── serialization.go │ ├── treebidimap.go │ └── treebidimap_test.go └── treemap │ ├── enumerable.go │ ├── iterator.go │ ├── serialization.go │ ├── treemap.go │ └── treemap_test.go ├── sets ├── hashset │ ├── hashset.go │ ├── hashset_test.go │ └── serialization.go ├── linkedhashset │ ├── enumerable.go │ ├── iterator.go │ ├── linkedhashset.go │ ├── linkedhashset_test.go │ └── serialization.go ├── sets.go └── treeset │ ├── enumerable.go │ ├── iterator.go │ ├── serialization.go │ ├── treeset.go │ └── treeset_test.go ├── stacks ├── arraystack │ ├── arraystack.go │ ├── arraystack_test.go │ ├── iterator.go │ └── serialization.go ├── linkedliststack │ ├── iterator.go │ ├── linkedliststack.go │ ├── linkedliststack_test.go │ └── serialization.go └── stacks.go ├── trees ├── avltree │ ├── avltree.go │ ├── avltree_test.go │ ├── iterator.go │ └── serialization.go ├── binaryheap │ ├── binaryheap.go │ ├── binaryheap_test.go │ ├── iterator.go │ └── serialization.go ├── btree │ ├── btree.go │ ├── btree_test.go │ ├── iterator.go │ └── serialization.go ├── redblacktree │ ├── iterator.go │ ├── redblacktree.go │ ├── redblacktree_test.go │ └── serialization.go └── trees.go └── utils ├── comparator.go ├── comparator_test.go ├── constraints.go ├── sort.go ├── sort_test.go ├── utils.go └── utils_test.go /.github/workflows/bench.yml: -------------------------------------------------------------------------------- 1 | name: Benchmark 2 | 3 | on: 4 | workflow_dispatch: 5 | input: {} 6 | 7 | jobs: 8 | bench: 9 | name: Generate Benchmark 10 | strategy: 11 | fail-fast: true 12 | matrix: 13 | os: 14 | - ubuntu-latest 15 | go: 16 | - "1.18" 17 | runs-on: ${{ matrix.os }} 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: Set up Go 22 | uses: actions/setup-go@v2 23 | with: 24 | go-version: ${{ matrix.go }} 25 | 26 | - name: Benchmark 27 | run: go test -bench=. -benchmem ./... | tee >benchmark.txt 28 | 29 | - name: Push Result 30 | run: | 31 | git config user.name gh-actions 32 | git config user.email gh-actions@github.com 33 | git add benchmark.txt 34 | git commit -m "[Action] Benchmark results" 35 | git push 36 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - "development" 7 | pull_request: 8 | branches: 9 | - "main" 10 | - "development" 11 | 12 | jobs: 13 | build: 14 | name: Build 15 | strategy: 16 | fail-fast: true 17 | matrix: 18 | os: 19 | - ubuntu-latest 20 | go: 21 | - "1.18" 22 | runs-on: ${{ matrix.os }} 23 | steps: 24 | - uses: actions/checkout@v2 25 | 26 | - name: Set up Go 27 | uses: actions/setup-go@v2 28 | with: 29 | go-version: ${{ matrix.go }} 30 | 31 | - name: Lint the code 32 | uses: golangci/golangci-lint-action@v2 33 | with: 34 | version: latest 35 | continue-on-error: true 36 | 37 | - name: Format code 38 | run: | 39 | go install golang.org/x/tools/cmd/goimports@latest 40 | goimports -w . 41 | 42 | - name: Vet 43 | run: go vet -v ./... 44 | 45 | - name: Build 46 | run: go build -v ./... 47 | 48 | - name: Test and Coverage Report 49 | run: go test -race -covermode=atomic -coverprofile=coverage.out ./... 50 | 51 | - name: Cyclomatic complexity 52 | run: | 53 | go install github.com/fzipp/gocyclo/cmd/gocyclo@latest 54 | gocyclo -avg -over 15 . 55 | 56 | - name: Upload code coverage 57 | uses: codecov/codecov-action@v1 58 | with: 59 | fail_ci_if_error: true 60 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | workflow_dispatch: 8 | inputs: 9 | tag: 10 | description: "Custom tag" 11 | required: false 12 | type: string 13 | 14 | 15 | jobs: 16 | build: 17 | name: Build Before Release 18 | strategy: 19 | fail-fast: true 20 | matrix: 21 | os: 22 | - "ubuntu-latest" 23 | - "macos-latest" 24 | go: 25 | - "1.18" 26 | 27 | runs-on: ${{ matrix.os }} 28 | steps: 29 | - uses: actions/checkout@v2 30 | - name: Set up Go 31 | uses: actions/setup-go@v2 32 | with: 33 | go-version: ${{ matrix.go }} 34 | - name: Build 35 | run: go build -v ./... 36 | 37 | - name: Test and Coverage Report 38 | run: go test -race -covermode=atomic -coverprofile=coverage.out ./... 39 | 40 | release: 41 | needs: build 42 | runs-on: "ubuntu-latest" 43 | steps: 44 | - uses: actions/checkout@v2 45 | - name: Bump version and push tag 46 | id: tag_version 47 | uses: mathieudutour/github-tag-action@v6.0 48 | with: 49 | github_token: ${{ secrets.GITHUB_TOKEN }} 50 | default_bump: "minor" 51 | custom_tag: "${{ github.event.inputs.tag }}" 52 | - name: Create a GitHub release 53 | uses: ncipollo/release-action@v1 54 | with: 55 | tag: ${{ steps.tag_version.outputs.new_tag }} 56 | name: Release ${{ steps.tag_version.outputs.new_tag }} 57 | body: ${{ steps.tag_version.outputs.changelog }} 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | .idea 27 | *.bkp 28 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | go: "1.18" 3 | tests: false 4 | issues: 5 | fix: true 6 | exclude: 7 | - "`assert(.*)Implementation` is unused" 8 | linters: 9 | disable-all: true 10 | enable: 11 | # Defaults 12 | - errcheck 13 | - gosimple 14 | - ineffassign 15 | - typecheck 16 | - unused 17 | - varcheck 18 | # Additional 19 | - goimports 20 | - dupl 21 | - whitespace 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022, Sohom Majumdar 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | ------------------------------------------------------------------------------- 26 | 27 | Copyright (c) 2015, Emir Pasic 28 | All rights reserved. 29 | 30 | Redistribution and use in source and binary forms, with or without 31 | modification, are permitted provided that the following conditions are met: 32 | 33 | * Redistributions of source code must retain the above copyright notice, this 34 | list of conditions and the following disclaimer. 35 | 36 | * Redistributions in binary form must reproduce the above copyright notice, 37 | this list of conditions and the following disclaimer in the documentation 38 | and/or other materials provided with the distribution. 39 | 40 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 41 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 43 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 44 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 46 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 47 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 48 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 49 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | 51 | ------------------------------------------------------------------------------- 52 | 53 | AVL Tree: 54 | 55 | Copyright (c) 2017 Benjamin Scher Purcell 56 | 57 | Permission to use, copy, modify, and distribute this software for any 58 | purpose with or without fee is hereby granted, provided that the above 59 | copyright notice and this permission notice appear in all copies. 60 | 61 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 62 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 63 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 64 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 65 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 66 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 67 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 68 | -------------------------------------------------------------------------------- /containers/containers.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package containers provides core interfaces and functions for data structures. 6 | // 7 | // Container is the base interface for all data structures to implement. 8 | // 9 | // Iterators provide stateful iterators. 10 | // 11 | // Enumerable provides Ruby inspired (each, select, map, find, any?, etc.) container functions. 12 | // 13 | // Serialization provides serializers (marshalers) and deserializers (unmarshalers). 14 | package containers 15 | 16 | import "github.com/daichi-m/go18ds/utils" 17 | 18 | // Container is base interface that all data structures implement. 19 | type Container[T any] interface { 20 | Empty() bool 21 | Size() int 22 | Clear() 23 | Values() []T 24 | } 25 | 26 | // GetSortedValues returns sorted container's elements with respect to the passed comparator. 27 | // Does not effect the ordering of elements within the container. 28 | func GetSortedValues[T comparable](container Container[T], comparator utils.Comparator[T]) []T { 29 | values := container.Values() 30 | if len(values) < 2 { 31 | return values 32 | } 33 | utils.Sort(values, comparator) 34 | return values 35 | } 36 | -------------------------------------------------------------------------------- /containers/containers_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // All data structures must implement the container structure 6 | 7 | package containers 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/daichi-m/go18ds/utils" 13 | ) 14 | 15 | // For testing purposes 16 | type ContainerTest[T ~int | ~string] struct { 17 | values []T 18 | } 19 | 20 | func (container ContainerTest[T]) Empty() bool { 21 | return len(container.values) == 0 22 | } 23 | 24 | func (container ContainerTest[T]) Size() int { 25 | return len(container.values) 26 | } 27 | 28 | func (container ContainerTest[T]) Clear() { 29 | container.values = []T{} 30 | } 31 | 32 | func (container ContainerTest[T]) Values() []T { 33 | return container.values 34 | } 35 | 36 | func TestGetSortedValuesInts(t *testing.T) { 37 | var container Container[int] = ContainerTest[int]{ 38 | values: []int{5, 1, 3, 2, 4}, 39 | } 40 | values := GetSortedValues(container, utils.NumberComparator[int]) 41 | for i := 1; i < container.Size(); i++ { 42 | if values[i-1] > values[i] { 43 | t.Errorf("Not sorted!") 44 | } 45 | } 46 | } 47 | 48 | func TestGetSortedValuesStrings(t *testing.T) { 49 | var container Container[string] = ContainerTest[string]{ 50 | values: []string{"g", "a", "d", "e", "f", "c", "b"}, 51 | } 52 | values := GetSortedValues(container, utils.StringComparator) 53 | for i := 1; i < container.Size(); i++ { 54 | if values[i-1] > values[i] { 55 | t.Errorf("Not sorted!") 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /containers/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package containers 6 | 7 | // EnumerableWithIndex provides functions for ordered containers whose values can be fetched by an index. 8 | type EnumerableWithIndex[T comparable] interface { 9 | // Each calls the given function once for each element, passing that element's index and value. 10 | Each(func(index int, value T)) 11 | 12 | // Map invokes the given function once for each element and returns a 13 | // container containing the values returned by the given function. 14 | // TODO would appreciate help on how to enforce this in containers (don't want to type assert when chaining) 15 | // Map(func(index int, value interface{}) interface{}) Container 16 | 17 | // Select returns a new container containing all elements for which the given function returns a true value. 18 | // TODO need help on how to enforce this in containers (don't want to type assert when chaining) 19 | // Select(func(index int, value interface{}) bool) Container 20 | 21 | // Any passes each element of the container to the given function and 22 | // returns true if the function ever returns true for any element. 23 | Any(func(index int, value T) bool) bool 24 | 25 | // All passes each element of the container to the given function and 26 | // returns true if the function returns true for all elements. 27 | All(func(index int, value T) bool) bool 28 | 29 | // Find passes each element of the container to the given function and returns 30 | // the first (index,value) for which the function is true or -1,nil otherwise 31 | // if no element matches the criteria. 32 | Find(func(index int, value T) bool) (int, T) 33 | } 34 | 35 | // EnumerableWithKey provides functions for ordered containers whose values whose elements are key/value pairs. 36 | type EnumerableWithKey[K comparable, V comparable] interface { 37 | // Each calls the given function once for each element, passing that element's key and value. 38 | Each(func(key K, value V)) 39 | 40 | // Map invokes the given function once for each element and returns a container 41 | // containing the values returned by the given function as key/value pairs. 42 | // TODO need help on how to enforce this in containers (don't want to type assert when chaining) 43 | // Map(func(key interface{}, value interface{}) (interface{}, interface{})) Container 44 | 45 | // Select returns a new container containing all elements for which the given function returns a true value. 46 | // TODO need help on how to enforce this in containers (don't want to type assert when chaining) 47 | // Select(func(key interface{}, value interface{}) bool) Container 48 | 49 | // Any passes each element of the container to the given function and 50 | // returns true if the function ever returns true for any element. 51 | Any(func(key K, value V) bool) bool 52 | 53 | // All passes each element of the container to the given function and 54 | // returns true if the function returns true for all elements. 55 | All(func(key K, value V) bool) bool 56 | 57 | // Find passes each element of the container to the given function and returns 58 | // the first (key,value) for which the function is true or nil,nil otherwise if no element 59 | // matches the criteria. 60 | Find(func(key K, value V) bool) (K, V) 61 | } 62 | -------------------------------------------------------------------------------- /containers/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package containers 6 | 7 | // IteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index. 8 | type IteratorWithIndex[T any] interface { 9 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 10 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 11 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 12 | // Modifies the state of the iterator. 13 | Next() bool 14 | 15 | // Value returns the current element's value. 16 | // Does not modify the state of the iterator. 17 | Value() T 18 | 19 | // Index returns the current element's index. 20 | // Does not modify the state of the iterator. 21 | Index() int 22 | 23 | // Begin resets the iterator to its initial state (one-before-first) 24 | // Call Next() to fetch the first element if any. 25 | Begin() 26 | 27 | // First moves the iterator to the first element and returns true if there was a first element in the container. 28 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 29 | // Modifies the state of the iterator. 30 | First() bool 31 | } 32 | 33 | // IteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. 34 | type IteratorWithKey[K any, V any] interface { 35 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 36 | // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). 37 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 38 | // Modifies the state of the iterator. 39 | Next() bool 40 | 41 | // Value returns the current element's value. 42 | // Does not modify the state of the iterator. 43 | Value() V 44 | 45 | // Key returns the current element's key. 46 | // Does not modify the state of the iterator. 47 | Key() K 48 | 49 | // Begin resets the iterator to its initial state (one-before-first) 50 | // Call Next() to fetch the first element if any. 51 | Begin() 52 | 53 | // First moves the iterator to the first element and returns true if there was a first element in the container. 54 | // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). 55 | // Modifies the state of the iterator. 56 | First() bool 57 | } 58 | 59 | // ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index. 60 | // 61 | // Essentially it is the same as IteratorWithIndex, but provides additional: 62 | // 63 | // Prev() function to enable traversal in reverse 64 | // 65 | // Last() function to move the iterator to the last element. 66 | // 67 | // End() function to move the iterator past the last element (one-past-the-end). 68 | type ReverseIteratorWithIndex[T comparable] interface { 69 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 70 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 71 | // Modifies the state of the iterator. 72 | Prev() bool 73 | 74 | // End moves the iterator past the last element (one-past-the-end). 75 | // Call Prev() to fetch the last element if any. 76 | End() 77 | 78 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 79 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 80 | // Modifies the state of the iterator. 81 | Last() bool 82 | 83 | IteratorWithIndex[T] 84 | } 85 | 86 | // ReverseIteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. 87 | // 88 | // Essentially it is the same as IteratorWithKey, but provides additional: 89 | // 90 | // Prev() function to enable traversal in reverse 91 | // 92 | // Last() function to move the iterator to the last element. 93 | type ReverseIteratorWithKey[K comparable, V comparable] interface { 94 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 95 | // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). 96 | // Modifies the state of the iterator. 97 | Prev() bool 98 | 99 | // End moves the iterator past the last element (one-past-the-end). 100 | // Call Prev() to fetch the last element if any. 101 | End() 102 | 103 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 104 | // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). 105 | // Modifies the state of the iterator. 106 | Last() bool 107 | 108 | IteratorWithKey[K, V] 109 | } 110 | -------------------------------------------------------------------------------- /containers/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package containers 6 | 7 | // JSONSerializer provides JSON serialization 8 | type JSONSerializer interface { 9 | // ToJSON outputs the JSON representation of containers's elements. 10 | ToJSON() ([]byte, error) 11 | } 12 | 13 | // JSONDeserializer provides JSON deserialization 14 | type JSONDeserializer interface { 15 | // FromJSON populates containers's elements from the input JSON representation. 16 | FromJSON([]byte) error 17 | } 18 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # GoDS (Go Data Structures) 2 | 3 | Various examples on how to use data structures. 4 | 5 | ## Examples 6 | 7 | - [ArrayList](https://github.com/emirpasic/gods/blob/master/examples/arraylist/arraylist.go) 8 | - [ArrayStack](https://github.com/emirpasic/gods/blob/master/examples/arraystack/arraystack.go) 9 | - [AVLTree](https://github.com/emirpasic/gods/blob/master/examples/avltree/avltree.go) 10 | - [BinaryHeap](https://github.com/emirpasic/gods/blob/master/examples/binaryheap/binaryheap.go) 11 | - [BTree](https://github.com/emirpasic/gods/blob/master/examples/btree/btree.go) 12 | - [Custom Comparator](https://github.com/emirpasic/gods/blob/master/examples/customcomparator/customcomparator.go) 13 | - [DoublyLinkedList](https://github.com/emirpasic/gods/blob/master/examples/doublylinkedlist/doublylinkedlist.go) 14 | - [EnumerableWithIndex](https://github.com/emirpasic/gods/blob/master/examples/enumerablewithindex/enumerablewithindex.go) 15 | - [EnumerableWithKey](https://github.com/emirpasic/gods/blob/master/examples/enumerablewithkey/enumerablewithkey.go) 16 | - [HashBidiMap](https://github.com/emirpasic/gods/blob/master/examples/hashbidimap/hashbidimap.go) 17 | - [HashMap](https://github.com/emirpasic/gods/blob/master/examples/hashmap/hashmap.go) 18 | - [HashSet](https://github.com/emirpasic/gods/blob/master/examples/hashset/hashset.go) 19 | - [IteratorWithIndex](https://github.com/emirpasic/gods/blob/master/examples/iteratorwithindex/iteratorwithindex.go) 20 | - [iteratorwithkey](https://github.com/emirpasic/gods/blob/master/examples/iteratorwithkey/iteratorwithkey.go) 21 | - [IteratorWithKey](https://github.com/emirpasic/gods/blob/master/examples/linkedliststack/linkedliststack.go) 22 | - [RedBlackTree](https://github.com/emirpasic/gods/blob/master/examples/redblacktree/redblacktree.go) 23 | - [RedBlackTreeExtended](https://github.com/emirpasic/gods/blob/master/examples/redblacktreeextended/redblacktreeextended.go) 24 | - [Serialization](https://github.com/emirpasic/gods/blob/master/examples/serialization/serialization.go) 25 | - [SinglyLinkedList](https://github.com/emirpasic/gods/blob/master/examples/singlylinkedlist/singlylinkedlist.go) 26 | - [Sort](https://github.com/emirpasic/gods/blob/master/examples/sort/sort.go) 27 | - [TreeBidiMap](https://github.com/emirpasic/gods/blob/master/examples/treebidimap/treebidimap.go) 28 | - [TreeMap](https://github.com/emirpasic/gods/blob/master/examples/treemap/treemap.go) 29 | - [TreeSet](https://github.com/emirpasic/gods/blob/master/examples/treeset/treeset.go) 30 | -------------------------------------------------------------------------------- /examples/arraylist/arraylist.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/lists/arraylist" 9 | "github.com/daichi-m/go18ds/utils" 10 | ) 11 | 12 | // ArrayListExample to demonstrate basic usage of ArrayList 13 | func main() { 14 | list := arraylist.New[string]() 15 | list.Add("a") // ["a"] 16 | list.Add("c", "b") // ["a","c","b"] 17 | list.Sort(utils.StringComparator) // ["a","b","c"] 18 | _, _ = list.Get(0) // "a",true 19 | _, _ = list.Get(100) // nil,false 20 | _ = list.Contains("a", "b", "c") // true 21 | _ = list.Contains("a", "b", "c", "d") // false 22 | list.Swap(0, 1) // ["b","a",c"] 23 | list.Remove(2) // ["b","a"] 24 | list.Remove(1) // ["b"] 25 | list.Remove(0) // [] 26 | list.Remove(0) // [] (ignored) 27 | _ = list.Empty() // true 28 | _ = list.Size() // 0 29 | list.Add("a") // ["a"] 30 | list.Clear() // [] 31 | } 32 | -------------------------------------------------------------------------------- /examples/arraystack/arraystack.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/stacks/arraystack" 8 | 9 | // ArrayStackExample to demonstrate basic usage of ArrayStack 10 | func main() { 11 | stack := arraystack.New[int]() // empty 12 | stack.Push(1) // 1 13 | stack.Push(2) // 1, 2 14 | stack.Values() // 2, 1 (LIFO order) 15 | _, _ = stack.Peek() // 2,true 16 | _, _ = stack.Pop() // 2, true 17 | _, _ = stack.Pop() // 1, true 18 | _, _ = stack.Pop() // nil, false (nothing to pop) 19 | stack.Push(1) // 1 20 | stack.Clear() // empty 21 | stack.Empty() // true 22 | stack.Size() // 0 23 | } 24 | -------------------------------------------------------------------------------- /examples/avltree/avltree.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | avl "github.com/daichi-m/go18ds/trees/avltree" 11 | ) 12 | 13 | // AVLTreeExample to demonstrate basic usage of AVLTree 14 | func main() { 15 | tree := avl.NewWithIntComparator[string]() // empty(keys are of type int) 16 | 17 | tree.Put(1, "x") // 1->x 18 | tree.Put(2, "b") // 1->x, 2->b (in order) 19 | tree.Put(1, "a") // 1->a, 2->b (in order, replacement) 20 | tree.Put(3, "c") // 1->a, 2->b, 3->c (in order) 21 | tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order) 22 | tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order) 23 | tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order) 24 | 25 | fmt.Println(tree) 26 | // 27 | // AVLTree 28 | // │ ┌── 6 29 | // │ ┌── 5 30 | // └── 4 31 | // │ ┌── 3 32 | // └── 2 33 | // └── 1 34 | 35 | _ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f"} (in order) 36 | _ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6} (in order) 37 | 38 | tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order) 39 | fmt.Println(tree) 40 | // 41 | // AVLTree 42 | // │ ┌── 6 43 | // │ ┌── 5 44 | // └── 4 45 | // └── 3 46 | // └── 1 47 | 48 | tree.Clear() // empty 49 | tree.Empty() // true 50 | tree.Size() // 0 51 | } 52 | -------------------------------------------------------------------------------- /examples/binaryheap/binaryheap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/trees/binaryheap" 9 | "github.com/daichi-m/go18ds/utils" 10 | ) 11 | 12 | // BinaryHeapExample to demonstrate basic usage of BinaryHeap 13 | func main() { 14 | 15 | // Min-heap 16 | heap := binaryheap.NewWithIntComparator() // empty (min-heap) 17 | heap.Push(2) // 2 18 | heap.Push(3) // 2, 3 19 | heap.Push(1) // 1, 3, 2 20 | heap.Values() // 1, 3, 2 21 | _, _ = heap.Peek() // 1,true 22 | _, _ = heap.Pop() // 1, true 23 | _, _ = heap.Pop() // 2, true 24 | _, _ = heap.Pop() // 3, true 25 | _, _ = heap.Pop() // nil, false (nothing to pop) 26 | heap.Push(1) // 1 27 | heap.Clear() // empty 28 | heap.Empty() // true 29 | heap.Size() // 0 30 | 31 | // Max-heap 32 | inverseIntComparator := func(a, b int) int { 33 | return -utils.NumberComparator(a, b) 34 | } 35 | heap = binaryheap.NewWith(inverseIntComparator) // empty (min-heap) 36 | heap.Push(2) // 2 37 | heap.Push(3) // 3, 2 38 | heap.Push(1) // 3, 2, 1 39 | heap.Values() // 3, 2, 1 40 | } 41 | -------------------------------------------------------------------------------- /examples/btree/btree.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/daichi-m/go18ds/trees/btree" 11 | ) 12 | 13 | // BTreeExample to demonstrate basic usage of BTree 14 | func main() { 15 | tree := btree.NewWithIntComparator[string](3) // empty (keys are of type int) 16 | 17 | tree.Put(1, "x") // 1->x 18 | tree.Put(2, "b") // 1->x, 2->b (in order) 19 | tree.Put(1, "a") // 1->a, 2->b (in order, replacement) 20 | tree.Put(3, "c") // 1->a, 2->b, 3->c (in order) 21 | tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order) 22 | tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order) 23 | tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order) 24 | tree.Put(7, "g") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f, 7->g (in order) 25 | 26 | fmt.Println(tree) 27 | // BTree 28 | // 1 29 | // 2 30 | // 3 31 | // 4 32 | // 5 33 | // 6 34 | // 7 35 | 36 | _ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f", "g"} (in order) 37 | _ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6, 7} (in order) 38 | 39 | tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order) 40 | fmt.Println(tree) 41 | // BTree 42 | // 1 43 | // 3 44 | // 4 45 | // 5 46 | // 6 47 | 48 | tree.Clear() // empty 49 | tree.Empty() // true 50 | tree.Size() // 0 51 | 52 | // Other: 53 | tree.Height() // gets the height of the tree 54 | tree.Left() // gets the left-most (min) node 55 | tree.LeftKey() // get the left-most (min) node's key 56 | tree.LeftValue() // get the left-most (min) node's value 57 | tree.Right() // get the right-most (max) node 58 | tree.RightKey() // get the right-most (max) node's key 59 | tree.RightValue() // get the right-most (max) node's value 60 | } 61 | -------------------------------------------------------------------------------- /examples/customcomparator/customcomparator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/daichi-m/go18ds/sets/treeset" 11 | ) 12 | 13 | // User model (id and name) 14 | type User struct { 15 | id int 16 | name string 17 | } 18 | 19 | // Comparator function (sort by IDs) 20 | func byID(c1, c2 User) int { 21 | 22 | switch { 23 | case c1.id > c2.id: 24 | return 1 25 | case c1.id < c2.id: 26 | return -1 27 | default: 28 | return 0 29 | } 30 | } 31 | 32 | // CustomComparatorExample to demonstrate basic usage of CustomComparator 33 | func main() { 34 | set := treeset.NewWith(byID) 35 | 36 | set.Add(User{2, "Second"}) 37 | set.Add(User{3, "Third"}) 38 | set.Add(User{1, "First"}) 39 | set.Add(User{4, "Fourth"}) 40 | 41 | fmt.Println(set) // {1 First}, {2 Second}, {3 Third}, {4 Fourth} 42 | } 43 | -------------------------------------------------------------------------------- /examples/doublylinkedlist/doublylinkedlist.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | dll "github.com/daichi-m/go18ds/lists/doublylinkedlist" 9 | "github.com/daichi-m/go18ds/utils" 10 | ) 11 | 12 | // DoublyLinkedListExample to demonstrate basic usage of DoublyLinkedList 13 | func main() { 14 | list := dll.New[string]() 15 | list.Add("a") // ["a"] 16 | list.Append("b") // ["a","b"] (same as Add()) 17 | list.Prepend("c") // ["c","a","b"] 18 | list.Sort(utils.StringComparator) // ["a","b","c"] 19 | _, _ = list.Get(0) // "a",true 20 | _, _ = list.Get(100) // nil,false 21 | _ = list.Contains("a", "b", "c") // true 22 | _ = list.Contains("a", "b", "c", "d") // false 23 | list.Remove(2) // ["a","b"] 24 | list.Remove(1) // ["a"] 25 | list.Remove(0) // [] 26 | list.Remove(0) // [] (ignored) 27 | _ = list.Empty() // true 28 | _ = list.Size() // 0 29 | list.Add("a") // ["a"] 30 | list.Clear() // [] 31 | } 32 | -------------------------------------------------------------------------------- /examples/enumerablewithindex/enumerablewithindex.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/daichi-m/go18ds/sets/treeset" 11 | ) 12 | 13 | func printSet(txt string, set *treeset.Set[int]) { 14 | fmt.Print(txt, "[ ") 15 | set.Each(func(index int, value int) { 16 | fmt.Print(value, " ") 17 | }) 18 | fmt.Println("]") 19 | } 20 | 21 | // EnumerableWithIndexExample to demonstrate basic usage of EnumerableWithIndex 22 | func main() { 23 | set := treeset.NewWithIntComparator() 24 | set.Add(2, 3, 4, 2, 5, 6, 7, 8) 25 | printSet("Initial", set) // [ 2 3 4 5 6 7 8 ] 26 | 27 | even := set.Select(func(index int, value int) bool { 28 | return value%2 == 0 29 | }) 30 | printSet("Even numbers", even) // [ 2 4 6 8 ] 31 | 32 | foundIndex, foundValue := set.Find(func(index int, value int) bool { 33 | return value%2 == 0 && value%3 == 0 34 | }) 35 | if foundIndex != -1 { 36 | fmt.Println("Number divisible by 2 and 3 found is", foundValue, "at index", foundIndex) // value: 6, index: 4 37 | } 38 | 39 | square := set.Map(func(index int, value int) int { 40 | return value * value 41 | }) 42 | printSet("Numbers squared", square) // [ 4 9 16 25 36 49 64 ] 43 | 44 | bigger := set.Any(func(index int, value int) bool { 45 | return value > 5 46 | }) 47 | fmt.Println("Set contains a number bigger than 5 is ", bigger) // true 48 | 49 | positive := set.All(func(index int, value int) bool { 50 | return value > 0 51 | }) 52 | fmt.Println("All numbers are positive is", positive) // true 53 | 54 | evenNumbersSquared := set.Select(func(index int, value int) bool { 55 | return value%2 == 0 56 | }).Map(func(index int, value int) int { 57 | return value * value 58 | }) 59 | printSet("Chaining", evenNumbersSquared) // [ 4 16 36 64 ] 60 | } 61 | -------------------------------------------------------------------------------- /examples/enumerablewithkey/enumerablewithkey.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/daichi-m/go18ds/maps/treemap" 11 | ) 12 | 13 | func printMap(txt string, m *treemap.Map[string, int]) { 14 | fmt.Print(txt, " { ") 15 | m.Each(func(key string, value int) { 16 | fmt.Print(key, ":", value, " ") 17 | }) 18 | fmt.Println("}") 19 | } 20 | 21 | // EunumerableWithKeyExample to demonstrate basic usage of EunumerableWithKey 22 | func main() { 23 | m := treemap.NewWithStringComparator[int]() 24 | m.Put("g", 7) 25 | m.Put("f", 6) 26 | m.Put("e", 5) 27 | m.Put("d", 4) 28 | m.Put("c", 3) 29 | m.Put("b", 2) 30 | m.Put("a", 1) 31 | printMap("Initial", m) // { a:1 b:2 c:3 d:4 e:5 f:6 g:7 } 32 | 33 | even := m.Select(func(key string, value int) bool { 34 | return value%2 == 0 35 | }) 36 | printMap("Elements with even values", even) // { b:2 d:4 f:6 } 37 | 38 | foundKey, foundValue := m.Find(func(key string, value int) bool { 39 | return value%2 == 0 && value%3 == 0 40 | }) 41 | if foundKey != "" { 42 | fmt.Println("Element with value divisible by 2 and 3 found is", foundValue, "with key", foundKey) // value: 6, index: 4 43 | } 44 | 45 | square := m.Map(func(key string, value int) (string, int) { 46 | return key + key, value * value 47 | }) 48 | printMap("Elements' values squared and letters duplicated", square) // { aa:1 bb:4 cc:9 dd:16 ee:25 ff:36 gg:49 } 49 | 50 | bigger := m.Any(func(key string, value int) bool { 51 | return value > 5 52 | }) 53 | fmt.Println("Map contains element whose value is bigger than 5 is", bigger) // true 54 | 55 | positive := m.All(func(key string, value int) bool { 56 | return value > 0 57 | }) 58 | fmt.Println("All map's elements have positive values is", positive) // true 59 | 60 | evenNumbersSquared := m.Select(func(key string, value int) bool { 61 | return value%2 == 0 62 | }).Map(func(key string, value int) (string, int) { 63 | return key, value * value 64 | }) 65 | printMap("Chaining", evenNumbersSquared) // { b:4 d:16 f:36 } 66 | } 67 | -------------------------------------------------------------------------------- /examples/godsort/godsort.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/utils" 8 | 9 | // SortExample to demonstrate basic usage of basic sort 10 | func main() { 11 | strings := []string{} // [] 12 | strings = append(strings, "d") // ["d"] 13 | strings = append(strings, "a") // ["d","a"] 14 | strings = append(strings, "b") // ["d","a",b" 15 | strings = append(strings, "c") // ["d","a",b","c"] 16 | utils.Sort(strings, utils.StringComparator) // ["a","b","c","d"] 17 | } 18 | -------------------------------------------------------------------------------- /examples/hashbidimap/hashbidimap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/maps/hashbidimap" 8 | 9 | // HashBidiMapExample to demonstrate basic usage of HashMap 10 | func main() { 11 | m := hashbidimap.New[int, string]() // empty 12 | m.Put(1, "x") // 1->x 13 | m.Put(3, "b") // 1->x, 3->b (random order) 14 | m.Put(1, "a") // 1->a, 3->b (random order) 15 | m.Put(2, "b") // 1->a, 2->b (random order) 16 | _, _ = m.GetKey("a") // 1, true 17 | _, _ = m.Get(2) // b, true 18 | _, _ = m.Get(3) // nil, false 19 | _ = m.Values() // []interface {}{"a", "b"} (random order) 20 | _ = m.Keys() // []interface {}{1, 2} (random order) 21 | m.Remove(1) // 2->b 22 | m.Clear() // empty 23 | m.Empty() // true 24 | m.Size() // 0 25 | } 26 | -------------------------------------------------------------------------------- /examples/hashmap/hashmap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/maps/hashmap" 8 | 9 | // HashMapExample to demonstrate basic usage of HashMap 10 | func main() { 11 | m := hashmap.New[int, string]() // empty 12 | m.Put(1, "x") // 1->x 13 | m.Put(2, "b") // 2->b, 1->x (random order) 14 | m.Put(1, "a") // 2->b, 1->a (random order) 15 | _, _ = m.Get(2) // b, true 16 | _, _ = m.Get(3) // nil, false 17 | _ = m.Values() // []interface {}{"b", "a"} (random order) 18 | _ = m.Keys() // []interface {}{1, 2} (random order) 19 | m.Remove(1) // 2->b 20 | m.Clear() // empty 21 | m.Empty() // true 22 | m.Size() // 0 23 | } 24 | -------------------------------------------------------------------------------- /examples/hashset/hashset.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/sets/hashset" 8 | 9 | // HashSetExample to demonstrate basic usage of HashSet 10 | func main() { 11 | set := hashset.New[int]() // empty (keys are of type int) 12 | set.Add(1) // 1 13 | set.Add(2, 2, 3, 4, 5) // 3, 1, 2, 4, 5 (random order, duplicates ignored) 14 | set.Remove(4) // 5, 3, 2, 1 (random order) 15 | set.Remove(2, 3) // 1, 5 (random order) 16 | set.Contains(1) // true 17 | set.Contains(1, 5) // true 18 | set.Contains(1, 6) // false 19 | _ = set.Values() // []int{5,1} (random order) 20 | set.Clear() // empty 21 | set.Empty() // true 22 | set.Size() // 0 23 | } 24 | -------------------------------------------------------------------------------- /examples/iteratorwithindex/iteratorwithindex.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/daichi-m/go18ds/sets/treeset" 11 | ) 12 | 13 | // IteratorWithIndexExample to demonstrate basic usage of IteratorWithIndex 14 | func main() { 15 | set := treeset.NewWithStringComparator() 16 | set.Add("a", "b", "c") 17 | it := set.Iterator() 18 | 19 | fmt.Print("\nForward iteration\n") 20 | for it.Next() { 21 | index, value := it.Index(), it.Value() 22 | fmt.Print("[", index, ":", value, "]") // [0:a][1:b][2:c] 23 | } 24 | 25 | fmt.Print("\nForward iteration (again)\n") 26 | for it.Begin(); it.Next(); { 27 | index, value := it.Index(), it.Value() 28 | fmt.Print("[", index, ":", value, "]") // [0:a][1:b][2:c] 29 | } 30 | 31 | fmt.Print("\nBackward iteration\n") 32 | for it.Prev() { 33 | index, value := it.Index(), it.Value() 34 | fmt.Print("[", index, ":", value, "]") // [2:c][1:b][0:a] 35 | } 36 | 37 | fmt.Print("\nBackward iteration (again)\n") 38 | for it.End(); it.Prev(); { 39 | index, value := it.Index(), it.Value() 40 | fmt.Print("[", index, ":", value, "]") // [2:c][1:b][0:a] 41 | } 42 | 43 | if it.First() { 44 | fmt.Print("\nFirst index: ", it.Index()) // First index: 0 45 | fmt.Print("\nFirst value: ", it.Value()) // First value: a 46 | } 47 | 48 | if it.Last() { 49 | fmt.Print("\nLast index: ", it.Index()) // Last index: 3 50 | fmt.Print("\nLast value: ", it.Value()) // Last value: c 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /examples/iteratorwithkey/iteratorwithkey.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/daichi-m/go18ds/maps/treemap" 11 | ) 12 | 13 | // IteratorWithKeyExample to demonstrate basic usage of IteratorWithKey 14 | func main() { 15 | m := treemap.NewWithIntComparator[string]() 16 | m.Put(1, "a") 17 | m.Put(2, "b") 18 | m.Put(3, "a") 19 | it := m.Iterator() 20 | 21 | fmt.Print("\nForward iteration\n") 22 | for it.Next() { 23 | key, value := it.Key(), it.Value() 24 | fmt.Print("[", key, ":", value, "]") // [0:a][1:b][2:c] 25 | } 26 | 27 | fmt.Print("\nForward iteration (again)\n") 28 | for it.Begin(); it.Next(); { 29 | key, value := it.Key(), it.Value() 30 | fmt.Print("[", key, ":", value, "]") // [0:a][1:b][2:c] 31 | } 32 | 33 | fmt.Print("\nBackward iteration\n") 34 | for it.Prev() { 35 | key, value := it.Key(), it.Value() 36 | fmt.Print("[", key, ":", value, "]") // [2:c][1:b][0:a] 37 | } 38 | 39 | fmt.Print("\nBackward iteration (again)\n") 40 | for it.End(); it.Prev(); { 41 | key, value := it.Key(), it.Value() 42 | fmt.Print("[", key, ":", value, "]") // [2:c][1:b][0:a] 43 | } 44 | 45 | if it.First() { 46 | fmt.Print("\nFirst key: ", it.Key()) // First key: 0 47 | fmt.Print("\nFirst value: ", it.Value()) // First value: a 48 | } 49 | 50 | if it.Last() { 51 | fmt.Print("\nLast key: ", it.Key()) // Last key: 3 52 | fmt.Print("\nLast value: ", it.Value()) // Last value: c 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/linkedhashmap/linkedhashmap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/maps/linkedhashmap" 8 | 9 | // LinkedHashMapExample to demonstrate basic usage of LinkedHashMapExample 10 | func main() { 11 | m := linkedhashmap.New[int, string]() // empty (keys are of type int) 12 | m.Put(2, "b") // 2->b 13 | m.Put(1, "x") // 2->b, 1->x (insertion-order) 14 | m.Put(1, "a") // 2->b, 1->a (insertion-order) 15 | _, _ = m.Get(2) // b, true 16 | _, _ = m.Get(3) // nil, false 17 | _ = m.Values() // []interface {}{"b", "a"} (insertion-order) 18 | _ = m.Keys() // []interface {}{2, 1} (insertion-order) 19 | m.Remove(1) // 2->b 20 | m.Clear() // empty 21 | m.Empty() // true 22 | m.Size() // 0 23 | } 24 | -------------------------------------------------------------------------------- /examples/linkedhashset/linkedhashset.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/sets/linkedhashset" 8 | 9 | // LinkedHashSetExample to demonstrate basic usage of LinkedHashSet 10 | func main() { 11 | set := linkedhashset.New[int]() // empty 12 | set.Add(5) // 5 13 | set.Add(4, 4, 3, 2, 1) // 5, 4, 3, 2, 1 (in insertion-order, duplicates ignored) 14 | set.Remove(4) // 5, 3, 2, 1 (in insertion-order) 15 | set.Remove(2, 3) // 5, 1 (in insertion-order) 16 | set.Contains(1) // true 17 | set.Contains(1, 5) // true 18 | set.Contains(1, 6) // false 19 | _ = set.Values() // []int{5, 1} (in insertion-order) 20 | set.Clear() // empty 21 | set.Empty() // true 22 | set.Size() // 0 23 | } 24 | -------------------------------------------------------------------------------- /examples/linkedliststack/linkedliststack.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import lls "github.com/daichi-m/go18ds/stacks/linkedliststack" 8 | 9 | // LinkedListStackExample to demonstrate basic usage of LinkedListStack 10 | func main() { 11 | stack := lls.New[int]() // empty 12 | stack.Push(1) // 1 13 | stack.Push(2) // 1, 2 14 | stack.Values() // 2, 1 (LIFO order) 15 | _, _ = stack.Peek() // 2,true 16 | _, _ = stack.Pop() // 2, true 17 | _, _ = stack.Pop() // 1, true 18 | _, _ = stack.Pop() // nil, false (nothing to pop) 19 | stack.Push(1) // 1 20 | stack.Clear() // empty 21 | stack.Empty() // true 22 | stack.Size() // 0 23 | } 24 | -------------------------------------------------------------------------------- /examples/redblacktree/redblacktree.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 11 | ) 12 | 13 | // RedBlackTreeExample to demonstrate basic usage of RedBlackTree 14 | func main() { 15 | tree := rbt.NewWithIntComparator[string]() // empty(keys are of type int) 16 | 17 | tree.Put(1, "x") // 1->x 18 | tree.Put(2, "b") // 1->x, 2->b (in order) 19 | tree.Put(1, "a") // 1->a, 2->b (in order, replacement) 20 | tree.Put(3, "c") // 1->a, 2->b, 3->c (in order) 21 | tree.Put(4, "d") // 1->a, 2->b, 3->c, 4->d (in order) 22 | tree.Put(5, "e") // 1->a, 2->b, 3->c, 4->d, 5->e (in order) 23 | tree.Put(6, "f") // 1->a, 2->b, 3->c, 4->d, 5->e, 6->f (in order) 24 | 25 | fmt.Println(tree) 26 | // 27 | // RedBlackTree 28 | // │ ┌── 6 29 | // │ ┌── 5 30 | // │ ┌── 4 31 | // │ │ └── 3 32 | // └── 2 33 | // └── 1 34 | 35 | _ = tree.Values() // []interface {}{"a", "b", "c", "d", "e", "f"} (in order) 36 | _ = tree.Keys() // []interface {}{1, 2, 3, 4, 5, 6} (in order) 37 | 38 | tree.Remove(2) // 1->a, 3->c, 4->d, 5->e, 6->f (in order) 39 | fmt.Println(tree) 40 | // 41 | // RedBlackTree 42 | // │ ┌── 6 43 | // │ ┌── 5 44 | // └── 4 45 | // │ ┌── 3 46 | // └── 1 47 | 48 | tree.Clear() // empty 49 | tree.Empty() // true 50 | tree.Size() // 0 51 | } 52 | -------------------------------------------------------------------------------- /examples/redblacktreeextended/redblacktreeextended.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package redblacktreeextended 6 | 7 | import ( 8 | "fmt" 9 | 10 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 11 | ) 12 | 13 | // RedBlackTreeExtended to demonstrate how to extend a RedBlackTree to include new functions 14 | type RedBlackTreeExtended struct { 15 | *rbt.Tree[int, string] 16 | } 17 | 18 | // GetMin gets the min value and flag if found 19 | func (tree *RedBlackTreeExtended) GetMin() (value string, found bool) { 20 | node, found := tree.getMinFromNode(tree.Root) 21 | if node != nil { 22 | return node.Value, found 23 | } 24 | return "", false 25 | } 26 | 27 | // GetMax gets the max value and flag if found 28 | func (tree *RedBlackTreeExtended) GetMax() (value string, found bool) { 29 | node, found := tree.getMaxFromNode(tree.Root) 30 | if node != nil { 31 | return node.Value, found 32 | } 33 | return "", false 34 | } 35 | 36 | // RemoveMin removes the min value and flag if found 37 | func (tree *RedBlackTreeExtended) RemoveMin() (value string, deleted bool) { 38 | node, found := tree.getMinFromNode(tree.Root) 39 | if found { 40 | tree.Remove(node.Key) 41 | return node.Value, found 42 | } 43 | return "", false 44 | } 45 | 46 | // RemoveMax removes the max value and flag if found 47 | func (tree *RedBlackTreeExtended) RemoveMax() (value string, deleted bool) { 48 | node, found := tree.getMaxFromNode(tree.Root) 49 | if found { 50 | tree.Remove(node.Key) 51 | return node.Value, found 52 | } 53 | return "", false 54 | } 55 | 56 | func (tree *RedBlackTreeExtended) getMinFromNode(node *rbt.Node[int, string]) ( 57 | foundNode *rbt.Node[int, string], found bool) { 58 | if node == nil { 59 | return nil, false 60 | } 61 | if node.Left == nil { 62 | return node, true 63 | } 64 | return tree.getMinFromNode(node.Left) 65 | } 66 | 67 | func (tree *RedBlackTreeExtended) getMaxFromNode(node *rbt.Node[int, string]) ( 68 | foundNode *rbt.Node[int, string], found bool) { 69 | if node == nil { 70 | return nil, false 71 | } 72 | if node.Right == nil { 73 | return node, true 74 | } 75 | return tree.getMaxFromNode(node.Right) 76 | } 77 | 78 | func print(tree *RedBlackTreeExtended) { 79 | max, _ := tree.GetMax() 80 | min, _ := tree.GetMin() 81 | fmt.Printf("Value for max key: %v \n", max) 82 | fmt.Printf("Value for min key: %v \n", min) 83 | fmt.Println(tree) 84 | } 85 | 86 | // RedBlackTreeExtendedExample main method on how to use the custom red-black tree above 87 | func main() { 88 | tree := RedBlackTreeExtended{rbt.NewWithIntComparator[string]()} 89 | 90 | tree.Put(1, "a") // 1->x (in order) 91 | tree.Put(2, "b") // 1->x, 2->b (in order) 92 | tree.Put(3, "c") // 1->x, 2->b, 3->c (in order) 93 | tree.Put(4, "d") // 1->x, 2->b, 3->c, 4->d (in order) 94 | tree.Put(5, "e") // 1->x, 2->b, 3->c, 4->d, 5->e (in order) 95 | 96 | print(&tree) 97 | // Value for max key: e 98 | // Value for min key: a 99 | // RedBlackTree 100 | // │ ┌── 5 101 | // │ ┌── 4 102 | // │ │ └── 3 103 | // └── 2 104 | // └── 1 105 | 106 | tree.RemoveMin() // 2->b, 3->c, 4->d, 5->e (in order) 107 | tree.RemoveMax() // 2->b, 3->c, 4->d (in order) 108 | tree.RemoveMin() // 3->c, 4->d (in order) 109 | tree.RemoveMax() // 3->c (in order) 110 | 111 | print(&tree) 112 | // Value for max key: c 113 | // Value for min key: c 114 | // RedBlackTree 115 | // └── 3 116 | } 117 | -------------------------------------------------------------------------------- /examples/serialization/serialization.go: -------------------------------------------------------------------------------- 1 | package serialization 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/daichi-m/go18ds/lists/arraylist" 7 | "github.com/daichi-m/go18ds/maps/hashmap" 8 | ) 9 | 10 | // ListSerializationExample demonstrates how to serialize and deserialize lists to and from JSON 11 | func ListSerializationExample() { 12 | list := arraylist.New[string]() 13 | list.Add("a", "b", "c") 14 | 15 | // Serialization (marshalling) 16 | json, err := list.ToJSON() 17 | if err != nil { 18 | fmt.Println(err) 19 | } 20 | fmt.Println(string(json)) // ["a","b","c"] 21 | 22 | // Deserialization (unmarshalling) 23 | json = []byte(`["a","b"]`) 24 | err = list.FromJSON(json) 25 | if err != nil { 26 | fmt.Println(err) 27 | } 28 | fmt.Println(list) // ArrayList ["a","b"] 29 | } 30 | 31 | // MapSerializationExample demonstrates how to serialize and deserialize maps to and from JSON 32 | func MapSerializationExample() { 33 | m := hashmap.New[string, string]() 34 | m.Put("a", "1") 35 | m.Put("b", "2") 36 | m.Put("c", "3") 37 | 38 | // Serialization (marshalling) 39 | json, err := m.ToJSON() 40 | if err != nil { 41 | fmt.Println(err) 42 | } 43 | fmt.Println(string(json)) // {"a":"1","b":"2","c":"3"} 44 | 45 | // Deserialization (unmarshalling) 46 | json = []byte(`{"a":"1","b":"2"}`) 47 | err = m.FromJSON(json) 48 | if err != nil { 49 | fmt.Println(err) 50 | } 51 | fmt.Println(m) // HashMap {"a":"1","b":"2"} 52 | } 53 | -------------------------------------------------------------------------------- /examples/singlylinkedlist/singlylinkedlist.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | sll "github.com/daichi-m/go18ds/lists/singlylinkedlist" 9 | "github.com/daichi-m/go18ds/utils" 10 | ) 11 | 12 | // SinglyLinkedListExample to demonstrate basic usage of SinglyLinkedList 13 | func main() { 14 | list := sll.New[string]() 15 | list.Add("a") // ["a"] 16 | list.Append("b") // ["a","b"] (same as Add()) 17 | list.Prepend("c") // ["c","a","b"] 18 | list.Sort(utils.StringComparator) // ["a","b","c"] 19 | _, _ = list.Get(0) // "a",true 20 | _, _ = list.Get(100) // nil,false 21 | _ = list.Contains("a", "b", "c") // true 22 | _ = list.Contains("a", "b", "c", "d") // false 23 | list.Remove(2) // ["a","b"] 24 | list.Remove(1) // ["a"] 25 | list.Remove(0) // [] 26 | list.Remove(0) // [] (ignored) 27 | _ = list.Empty() // true 28 | _ = list.Size() // 0 29 | list.Add("a") // ["a"] 30 | list.Clear() // [] 31 | } 32 | -------------------------------------------------------------------------------- /examples/treebidimap/treebidimap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/maps/treebidimap" 9 | "github.com/daichi-m/go18ds/utils" 10 | ) 11 | 12 | // TreeBidiMapExample to demonstrate basic usage of TreeBidiMap 13 | func main() { 14 | m := treebidimap.NewWith(utils.NumberComparator[int], utils.StringComparator) 15 | m.Put(1, "x") // 1->x 16 | m.Put(3, "b") // 1->x, 3->b (ordered) 17 | m.Put(1, "a") // 1->a, 3->b (ordered) 18 | m.Put(2, "b") // 1->a, 2->b (ordered) 19 | _, _ = m.GetKey("a") // 1, true 20 | _, _ = m.Get(2) // b, true 21 | _, _ = m.Get(3) // nil, false 22 | _ = m.Values() // []interface {}{"a", "b"} (ordered) 23 | _ = m.Keys() // []interface {}{1, 2} (ordered) 24 | m.Remove(1) // 2->b 25 | m.Clear() // empty 26 | m.Empty() // true 27 | m.Size() // 0 28 | } 29 | -------------------------------------------------------------------------------- /examples/treemap/treemap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/maps/treemap" 8 | 9 | // TreeMapExample to demonstrate basic usage of TreeMap 10 | func main() { 11 | m := treemap.NewWithIntComparator[string]() // empty (keys are of type int) 12 | m.Put(1, "x") // 1->x 13 | m.Put(2, "b") // 1->x, 2->b (in order) 14 | m.Put(1, "a") // 1->a, 2->b (in order) 15 | _, _ = m.Get(2) // b, true 16 | _, _ = m.Get(3) // nil, false 17 | _ = m.Values() // []interface {}{"a", "b"} (in order) 18 | _ = m.Keys() // []interface {}{1, 2} (in order) 19 | m.Remove(1) // 2->b 20 | m.Clear() // empty 21 | m.Empty() // true 22 | m.Size() // 0 23 | } 24 | -------------------------------------------------------------------------------- /examples/treeset/treeset.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/daichi-m/go18ds/sets/treeset" 8 | 9 | // TreeSetExample to demonstrate basic usage of TreeSet 10 | func main() { 11 | set := treeset.NewWithIntComparator() // empty 12 | set.Add(1) // 1 13 | set.Add(2, 2, 3, 4, 5) // 1, 2, 3, 4, 5 (in order, duplicates ignored) 14 | set.Remove(4) // 1, 2, 3, 5 (in order) 15 | set.Remove(2, 3) // 1, 5 (in order) 16 | set.Contains(1) // true 17 | set.Contains(1, 5) // true 18 | set.Contains(1, 6) // false 19 | _ = set.Values() // []int{1,5} (in order) 20 | set.Clear() // empty 21 | set.Empty() // true 22 | set.Size() // 0 23 | } 24 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/daichi-m/go18ds 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daichi-m/go18ds/bc64532cc3920b72d57f1e2e3af83b3f4163b0f0/go.sum -------------------------------------------------------------------------------- /lists/arraylist/arraylist.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package arraylist implements the array list. 6 | // 7 | // Structure is not thread safe. 8 | // 9 | // Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29 10 | package arraylist 11 | 12 | import ( 13 | "fmt" 14 | "strings" 15 | 16 | "github.com/daichi-m/go18ds/lists" 17 | "github.com/daichi-m/go18ds/utils" 18 | ) 19 | 20 | func assertListImplementation() { 21 | var _ lists.List[string] = (*List[string])(nil) 22 | } 23 | 24 | // List holds the elements in a slice 25 | type List[T comparable] struct { 26 | elements []T 27 | size int 28 | } 29 | 30 | const ( 31 | growthFactor = float32(2.0) // growth by 100% 32 | shrinkFactor = float32(0.25) // shrink when size is 25% of capacity (0 means never shrink) 33 | ) 34 | 35 | // New instantiates a new list and adds the passed values, if any, to the list 36 | func New[T comparable](values ...T) *List[T] { 37 | list := &List[T]{} 38 | if len(values) > 0 { 39 | list.Add(values...) 40 | } 41 | return list 42 | } 43 | 44 | // Add appends a value at the end of the list 45 | func (list *List[T]) Add(values ...T) { 46 | list.growBy(len(values)) 47 | for _, value := range values { 48 | list.elements[list.size] = value 49 | list.size++ 50 | } 51 | } 52 | 53 | // Get returns the element at index. 54 | // Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false. 55 | func (list *List[T]) Get(index int) (T, bool) { 56 | if !list.withinRange(index) { 57 | return *new(T), false 58 | } 59 | 60 | return list.elements[index], true 61 | } 62 | 63 | // Remove removes the element at the given index from the list. 64 | func (list *List[T]) Remove(index int) { 65 | if !list.withinRange(index) { 66 | return 67 | } 68 | 69 | list.elements[index] = *new(T) // cleanup reference 70 | copy(list.elements[index:], list.elements[index+1:list.size]) // shift to the left by one (slow operation, need ways to optimize this) 71 | list.size-- 72 | 73 | list.shrink() 74 | } 75 | 76 | // Contains checks if elements (one or more) are present in the set. 77 | // All elements have to be present in the set for the method to return true. 78 | // Performance time complexity of n^2. 79 | // Returns true if no arguments are passed at all, i.e. set is always super-set of empty set. 80 | func (list *List[T]) Contains(values ...T) bool { 81 | for _, searchValue := range values { 82 | found := false 83 | for _, element := range list.elements { 84 | if element == searchValue { 85 | found = true 86 | break 87 | } 88 | } 89 | if !found { 90 | return false 91 | } 92 | } 93 | return true 94 | } 95 | 96 | // Values returns all elements in the list. 97 | func (list *List[T]) Values() []T { 98 | newElements := make([]T, list.size, list.size) 99 | copy(newElements, list.elements[:list.size]) 100 | return newElements 101 | } 102 | 103 | //IndexOf returns index of provided element 104 | func (list *List[T]) IndexOf(value interface{}) int { 105 | if list.size == 0 { 106 | return -1 107 | } 108 | for index, element := range list.elements { 109 | if element == value { 110 | return index 111 | } 112 | } 113 | return -1 114 | } 115 | 116 | // Empty returns true if list does not contain any elements. 117 | func (list *List[T]) Empty() bool { 118 | return list.size == 0 119 | } 120 | 121 | // Size returns number of elements within the list. 122 | func (list *List[T]) Size() int { 123 | return list.size 124 | } 125 | 126 | // Clear removes all elements from the list. 127 | func (list *List[T]) Clear() { 128 | list.size = 0 129 | list.elements = []T{} 130 | } 131 | 132 | // Sort sorts values (in-place) using. 133 | func (list *List[T]) Sort(comparator utils.Comparator[T]) { 134 | if len(list.elements) < 2 { 135 | return 136 | } 137 | utils.Sort(list.elements[:list.size], comparator) 138 | } 139 | 140 | // Swap swaps the two values at the specified positions. 141 | func (list *List[T]) Swap(i, j int) { 142 | if list.withinRange(i) && list.withinRange(j) { 143 | list.elements[i], list.elements[j] = list.elements[j], list.elements[i] 144 | } 145 | } 146 | 147 | // Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. 148 | // Does not do anything if position is negative or bigger than list's size 149 | // Note: position equal to list's size is valid, i.e. append. 150 | func (list *List[T]) Insert(index int, values ...T) { 151 | if !list.withinRange(index) { 152 | // Append 153 | if index == list.size { 154 | list.Add(values...) 155 | } 156 | return 157 | } 158 | 159 | l := len(values) 160 | list.growBy(l) 161 | list.size += l 162 | copy(list.elements[index+l:], list.elements[index:list.size-l]) 163 | copy(list.elements[index:], values) 164 | } 165 | 166 | // Set the value at specified index 167 | // Does not do anything if position is negative or bigger than list's size 168 | // Note: position equal to list's size is valid, i.e. append. 169 | func (list *List[T]) Set(index int, value T) { 170 | if !list.withinRange(index) { 171 | // Append 172 | if index == list.size { 173 | list.Add(value) 174 | } 175 | return 176 | } 177 | 178 | list.elements[index] = value 179 | } 180 | 181 | // String returns a string representation of container 182 | func (list *List[T]) String() string { 183 | str := "ArrayList\n" 184 | values := []string{} 185 | for _, value := range list.elements[:list.size] { 186 | values = append(values, fmt.Sprintf("%v", value)) 187 | } 188 | str += strings.Join(values, ", ") 189 | return str 190 | } 191 | 192 | // Check that the index is within bounds of the list 193 | func (list *List[T]) withinRange(index int) bool { 194 | return index >= 0 && index < list.size 195 | } 196 | 197 | func (list *List[T]) resize(cap int) { 198 | newElements := make([]T, cap, cap) 199 | copy(newElements, list.elements) 200 | list.elements = newElements 201 | } 202 | 203 | // Expand the array if necessary, i.e. capacity will be reached if we add n elements 204 | func (list *List[T]) growBy(n int) { 205 | // When capacity is reached, grow by a factor of growthFactor and add number of elements 206 | currentCapacity := cap(list.elements) 207 | if list.size+n >= currentCapacity { 208 | newCapacity := int(growthFactor * float32(currentCapacity+n)) 209 | list.resize(newCapacity) 210 | } 211 | } 212 | 213 | // Shrink the array if necessary, i.e. when size is shrinkFactor percent of current capacity 214 | func (list *List[T]) shrink() { 215 | if shrinkFactor == 0.0 { 216 | return 217 | } 218 | // Shrink when size is at shrinkFactor * capacity 219 | currentCapacity := cap(list.elements) 220 | if list.size <= int(float32(currentCapacity)*shrinkFactor) { 221 | list.resize(list.size) 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /lists/arraylist/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arraylist 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertEnumerableImplementation() { 10 | var _ containers.EnumerableWithIndex[string] = (*List[string])(nil) 11 | } 12 | 13 | // Each calls the given function once for each element, passing that element's index and value. 14 | func (list *List[T]) Each(f func(index int, value T)) { 15 | iterator := list.Iterator() 16 | for iterator.Next() { 17 | f(iterator.Index(), iterator.Value()) 18 | } 19 | } 20 | 21 | // Map invokes the given function once for each element and returns a 22 | // container containing the values returned by the given function. 23 | func (list *List[T]) Map(f func(index int, value T) T) *List[T] { 24 | newList := &List[T]{} 25 | iterator := list.Iterator() 26 | for iterator.Next() { 27 | newList.Add(f(iterator.Index(), iterator.Value())) 28 | } 29 | return newList 30 | } 31 | 32 | // Select returns a new container containing all elements for which the given function returns a true value. 33 | func (list *List[T]) Select(f func(index int, value T) bool) *List[T] { 34 | newList := &List[T]{} 35 | iterator := list.Iterator() 36 | for iterator.Next() { 37 | if f(iterator.Index(), iterator.Value()) { 38 | newList.Add(iterator.Value()) 39 | } 40 | } 41 | return newList 42 | } 43 | 44 | // Any passes each element of the collection to the given function and 45 | // returns true if the function ever returns true for any element. 46 | func (list *List[T]) Any(f func(index int, value T) bool) bool { 47 | iterator := list.Iterator() 48 | for iterator.Next() { 49 | if f(iterator.Index(), iterator.Value()) { 50 | return true 51 | } 52 | } 53 | return false 54 | } 55 | 56 | // All passes each element of the collection to the given function and 57 | // returns true if the function returns true for all elements. 58 | func (list *List[T]) All(f func(index int, value T) bool) bool { 59 | iterator := list.Iterator() 60 | for iterator.Next() { 61 | if !f(iterator.Index(), iterator.Value()) { 62 | return false 63 | } 64 | } 65 | return true 66 | } 67 | 68 | // Find passes each element of the container to the given function and returns 69 | // the first (index,value) for which the function is true or -1,nil otherwise 70 | // if no element matches the criteria. 71 | func (list *List[T]) Find(f func(index int, value T) bool) (int, T) { 72 | iterator := list.Iterator() 73 | for iterator.Next() { 74 | if f(iterator.Index(), iterator.Value()) { 75 | return iterator.Index(), iterator.Value() 76 | } 77 | } 78 | return -1, *new(T) 79 | } 80 | -------------------------------------------------------------------------------- /lists/arraylist/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arraylist 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.ReverseIteratorWithIndex[string] = (*Iterator[string])(nil) 11 | } 12 | 13 | // Iterator holding the iterator's state 14 | type Iterator[T comparable] struct { 15 | list *List[T] 16 | index int 17 | } 18 | 19 | // Iterator returns a stateful iterator whose values can be fetched by an index. 20 | func (list *List[T]) Iterator() Iterator[T] { 21 | return Iterator[T]{list: list, index: -1} 22 | } 23 | 24 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 25 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 26 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 27 | // Modifies the state of the iterator. 28 | func (iterator *Iterator[T]) Next() bool { 29 | if iterator.index < iterator.list.size { 30 | iterator.index++ 31 | } 32 | return iterator.list.withinRange(iterator.index) 33 | } 34 | 35 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 36 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 37 | // Modifies the state of the iterator. 38 | func (iterator *Iterator[T]) Prev() bool { 39 | if iterator.index >= 0 { 40 | iterator.index-- 41 | } 42 | return iterator.list.withinRange(iterator.index) 43 | } 44 | 45 | // Value returns the current element's value. 46 | // Does not modify the state of the iterator. 47 | func (iterator *Iterator[T]) Value() T { 48 | return iterator.list.elements[iterator.index] 49 | } 50 | 51 | // Index returns the current element's index. 52 | // Does not modify the state of the iterator. 53 | func (iterator *Iterator[T]) Index() int { 54 | return iterator.index 55 | } 56 | 57 | // Begin resets the iterator to its initial state (one-before-first) 58 | // Call Next() to fetch the first element if any. 59 | func (iterator *Iterator[T]) Begin() { 60 | iterator.index = -1 61 | } 62 | 63 | // End moves the iterator past the last element (one-past-the-end). 64 | // Call Prev() to fetch the last element if any. 65 | func (iterator *Iterator[T]) End() { 66 | iterator.index = iterator.list.size 67 | } 68 | 69 | // First moves the iterator to the first element and returns true if there was a first element in the container. 70 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 71 | // Modifies the state of the iterator. 72 | func (iterator *Iterator[T]) First() bool { 73 | iterator.Begin() 74 | return iterator.Next() 75 | } 76 | 77 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 78 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 79 | // Modifies the state of the iterator. 80 | func (iterator *Iterator[T]) Last() bool { 81 | iterator.End() 82 | return iterator.Prev() 83 | } 84 | -------------------------------------------------------------------------------- /lists/arraylist/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arraylist 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | ) 12 | 13 | func assertSerializationImplementation() { 14 | var _ containers.JSONSerializer = (*List[string])(nil) 15 | var _ containers.JSONDeserializer = (*List[string])(nil) 16 | } 17 | 18 | // ToJSON outputs the JSON representation of list's elements. 19 | func (list *List[T]) ToJSON() ([]byte, error) { 20 | return json.Marshal(list.elements[:list.size]) 21 | } 22 | 23 | // FromJSON populates list's elements from the input JSON representation. 24 | func (list *List[T]) FromJSON(data []byte) error { 25 | err := json.Unmarshal(data, &list.elements) 26 | if err == nil { 27 | list.size = len(list.elements) 28 | } 29 | return err 30 | } 31 | -------------------------------------------------------------------------------- /lists/doublylinkedlist/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package doublylinkedlist 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertEnumerableImplementation() { 10 | var _ containers.EnumerableWithIndex[string] = (*List[string])(nil) 11 | } 12 | 13 | // Each calls the given function once for each element, passing that element's index and value. 14 | func (list *List[T]) Each(f func(index int, value T)) { 15 | iterator := list.Iterator() 16 | for iterator.Next() { 17 | f(iterator.Index(), iterator.Value()) 18 | } 19 | } 20 | 21 | // Map invokes the given function once for each element and returns a 22 | // container containing the values returned by the given function. 23 | func (list *List[T]) Map(f func(index int, value T) T) *List[T] { 24 | newList := &List[T]{} 25 | iterator := list.Iterator() 26 | for iterator.Next() { 27 | newList.Add(f(iterator.Index(), iterator.Value())) 28 | } 29 | return newList 30 | } 31 | 32 | // Select returns a new container containing all elements for which the given function returns a true value. 33 | func (list *List[T]) Select(f func(index int, value T) bool) *List[T] { 34 | newList := &List[T]{} 35 | iterator := list.Iterator() 36 | for iterator.Next() { 37 | if f(iterator.Index(), iterator.Value()) { 38 | newList.Add(iterator.Value()) 39 | } 40 | } 41 | return newList 42 | } 43 | 44 | // Any passes each element of the container to the given function and 45 | // returns true if the function ever returns true for any element. 46 | func (list *List[T]) Any(f func(index int, value T) bool) bool { 47 | iterator := list.Iterator() 48 | for iterator.Next() { 49 | if f(iterator.Index(), iterator.Value()) { 50 | return true 51 | } 52 | } 53 | return false 54 | } 55 | 56 | // All passes each element of the container to the given function and 57 | // returns true if the function returns true for all elements. 58 | func (list *List[T]) All(f func(index int, value T) bool) bool { 59 | iterator := list.Iterator() 60 | for iterator.Next() { 61 | if !f(iterator.Index(), iterator.Value()) { 62 | return false 63 | } 64 | } 65 | return true 66 | } 67 | 68 | // Find passes each element of the container to the given function and returns 69 | // the first (index,value) for which the function is true or -1,nil otherwise 70 | // if no element matches the criteria. 71 | func (list *List[T]) Find(f func(index int, value T) bool) (index int, value T) { 72 | iterator := list.Iterator() 73 | for iterator.Next() { 74 | if f(iterator.Index(), iterator.Value()) { 75 | return iterator.Index(), iterator.Value() 76 | } 77 | } 78 | return -1, *new(T) 79 | } 80 | -------------------------------------------------------------------------------- /lists/doublylinkedlist/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package doublylinkedlist 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.ReverseIteratorWithIndex[string] = (*Iterator[string])(nil) 11 | } 12 | 13 | // Iterator holding the iterator's state 14 | type Iterator[T comparable] struct { 15 | list *List[T] 16 | index int 17 | element *element[T] 18 | } 19 | 20 | // Iterator returns a stateful iterator whose values can be fetched by an index. 21 | func (list *List[T]) Iterator() Iterator[T] { 22 | return Iterator[T]{list: list, index: -1, element: nil} 23 | } 24 | 25 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 26 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 27 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 28 | // Modifies the state of the iterator. 29 | func (iterator *Iterator[T]) Next() bool { 30 | if iterator.index < iterator.list.size { 31 | iterator.index++ 32 | } 33 | if !iterator.list.withinRange(iterator.index) { 34 | iterator.element = nil 35 | return false 36 | } 37 | if iterator.index != 0 { 38 | iterator.element = iterator.element.next 39 | } else { 40 | iterator.element = iterator.list.first 41 | } 42 | return true 43 | } 44 | 45 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 46 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 47 | // Modifies the state of the iterator. 48 | func (iterator *Iterator[T]) Prev() bool { 49 | if iterator.index >= 0 { 50 | iterator.index-- 51 | } 52 | if !iterator.list.withinRange(iterator.index) { 53 | iterator.element = nil 54 | return false 55 | } 56 | if iterator.index == iterator.list.size-1 { 57 | iterator.element = iterator.list.last 58 | } else { 59 | iterator.element = iterator.element.prev 60 | } 61 | return iterator.list.withinRange(iterator.index) 62 | } 63 | 64 | // Value returns the current element's value. 65 | // Does not modify the state of the iterator. 66 | func (iterator *Iterator[T]) Value() T { 67 | return iterator.element.value 68 | } 69 | 70 | // Index returns the current element's index. 71 | // Does not modify the state of the iterator. 72 | func (iterator *Iterator[T]) Index() int { 73 | return iterator.index 74 | } 75 | 76 | // Begin resets the iterator to its initial state (one-before-first) 77 | // Call Next() to fetch the first element if any. 78 | func (iterator *Iterator[T]) Begin() { 79 | iterator.index = -1 80 | iterator.element = nil 81 | } 82 | 83 | // End moves the iterator past the last element (one-past-the-end). 84 | // Call Prev() to fetch the last element if any. 85 | func (iterator *Iterator[T]) End() { 86 | iterator.index = iterator.list.size 87 | iterator.element = iterator.list.last 88 | } 89 | 90 | // First moves the iterator to the first element and returns true if there was a first element in the container. 91 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 92 | // Modifies the state of the iterator. 93 | func (iterator *Iterator[T]) First() bool { 94 | iterator.Begin() 95 | return iterator.Next() 96 | } 97 | 98 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 99 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 100 | // Modifies the state of the iterator. 101 | func (iterator *Iterator[T]) Last() bool { 102 | iterator.End() 103 | return iterator.Prev() 104 | } 105 | -------------------------------------------------------------------------------- /lists/doublylinkedlist/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package doublylinkedlist 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | ) 12 | 13 | func assertSerializationImplementation() { 14 | var _ containers.JSONSerializer = (*List[string])(nil) 15 | var _ containers.JSONDeserializer = (*List[string])(nil) 16 | } 17 | 18 | // ToJSON outputs the JSON representation of list's elements. 19 | func (list *List[T]) ToJSON() ([]byte, error) { 20 | return json.Marshal(list.Values()) 21 | } 22 | 23 | // FromJSON populates list's elements from the input JSON representation. 24 | func (list *List[T]) FromJSON(data []byte) error { 25 | elements := []T{} 26 | err := json.Unmarshal(data, &elements) 27 | if err == nil { 28 | list.Clear() 29 | list.Add(elements...) 30 | } 31 | return err 32 | } 33 | -------------------------------------------------------------------------------- /lists/lists.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package lists provides an abstract List interface. 6 | // 7 | // In computer science, a list or sequence is an abstract data type that represents an ordered sequence of values, where the same value may occur more than once. An instance of a list is a computer representation of the mathematical concept of a finite sequence; the (potentially) infinite analog of a list is a stream. Lists are a basic example of containers, as they contain other values. If the same value occurs multiple times, each occurrence is considered a distinct item. 8 | // 9 | // Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29 10 | package lists 11 | 12 | import ( 13 | "github.com/daichi-m/go18ds/containers" 14 | "github.com/daichi-m/go18ds/utils" 15 | ) 16 | 17 | // List interface that all lists implement 18 | type List[T comparable] interface { 19 | Get(index int) (T, bool) 20 | Remove(index int) 21 | Add(values ...T) 22 | Contains(values ...T) bool 23 | Sort(comparator utils.Comparator[T]) 24 | Swap(index1, index2 int) 25 | Insert(index int, values ...T) 26 | Set(index int, value T) 27 | 28 | containers.Container[T] 29 | // Empty() bool 30 | // Size() int 31 | // Clear() 32 | // Values() []T 33 | } 34 | -------------------------------------------------------------------------------- /lists/singlylinkedlist/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package singlylinkedlist 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertEnumerableImplementation() { 10 | var _ containers.EnumerableWithIndex[string] = (*List[string])(nil) 11 | } 12 | 13 | // Each calls the given function once for each element, passing that element's index and value. 14 | func (list *List[T]) Each(f func(index int, value T)) { 15 | iterator := list.Iterator() 16 | for iterator.Next() { 17 | f(iterator.Index(), iterator.Value()) 18 | } 19 | } 20 | 21 | // Map invokes the given function once for each element and returns a 22 | // container containing the values returned by the given function. 23 | func (list *List[T]) Map(f func(index int, value T) T) *List[T] { 24 | newList := &List[T]{} 25 | iterator := list.Iterator() 26 | for iterator.Next() { 27 | newList.Add(f(iterator.Index(), iterator.Value())) 28 | } 29 | return newList 30 | } 31 | 32 | // Select returns a new container containing all elements for which the given function returns a true value. 33 | func (list *List[T]) Select(f func(index int, value T) bool) *List[T] { 34 | newList := &List[T]{} 35 | iterator := list.Iterator() 36 | for iterator.Next() { 37 | if f(iterator.Index(), iterator.Value()) { 38 | newList.Add(iterator.Value()) 39 | } 40 | } 41 | return newList 42 | } 43 | 44 | // Any passes each element of the container to the given function and 45 | // returns true if the function ever returns true for any element. 46 | func (list *List[T]) Any(f func(index int, value T) bool) bool { 47 | iterator := list.Iterator() 48 | for iterator.Next() { 49 | if f(iterator.Index(), iterator.Value()) { 50 | return true 51 | } 52 | } 53 | return false 54 | } 55 | 56 | // All passes each element of the container to the given function and 57 | // returns true if the function returns true for all elements. 58 | func (list *List[T]) All(f func(index int, value T) bool) bool { 59 | iterator := list.Iterator() 60 | for iterator.Next() { 61 | if !f(iterator.Index(), iterator.Value()) { 62 | return false 63 | } 64 | } 65 | return true 66 | } 67 | 68 | // Find passes each element of the container to the given function and returns 69 | // the first (index,value) for which the function is true or -1,nil otherwise 70 | // if no element matches the criteria. 71 | func (list *List[T]) Find(f func(index int, value T) bool) (index int, value T) { 72 | iterator := list.Iterator() 73 | for iterator.Next() { 74 | if f(iterator.Index(), iterator.Value()) { 75 | return iterator.Index(), iterator.Value() 76 | } 77 | } 78 | return -1, *new(T) 79 | } 80 | -------------------------------------------------------------------------------- /lists/singlylinkedlist/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package singlylinkedlist 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.IteratorWithIndex[string] = (*Iterator[string])(nil) 11 | } 12 | 13 | // Iterator holding the iterator's state 14 | type Iterator[T comparable] struct { 15 | list *List[T] 16 | index int 17 | element *element[T] 18 | } 19 | 20 | // Iterator returns a stateful iterator whose values can be fetched by an index. 21 | func (list *List[T]) Iterator() Iterator[T] { 22 | return Iterator[T]{list: list, index: -1, element: nil} 23 | } 24 | 25 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 26 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 27 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 28 | // Modifies the state of the iterator. 29 | func (iterator *Iterator[T]) Next() bool { 30 | if iterator.index < iterator.list.size { 31 | iterator.index++ 32 | } 33 | if !iterator.list.withinRange(iterator.index) { 34 | iterator.element = nil 35 | return false 36 | } 37 | if iterator.index == 0 { 38 | iterator.element = iterator.list.first 39 | } else { 40 | iterator.element = iterator.element.next 41 | } 42 | return true 43 | } 44 | 45 | // Value returns the current element's value. 46 | // Does not modify the state of the iterator. 47 | func (iterator *Iterator[T]) Value() T { 48 | return iterator.element.value 49 | } 50 | 51 | // Index returns the current element's index. 52 | // Does not modify the state of the iterator. 53 | func (iterator *Iterator[T]) Index() int { 54 | return iterator.index 55 | } 56 | 57 | // Begin resets the iterator to its initial state (one-before-first) 58 | // Call Next() to fetch the first element if any. 59 | func (iterator *Iterator[T]) Begin() { 60 | iterator.index = -1 61 | iterator.element = nil 62 | } 63 | 64 | // First moves the iterator to the first element and returns true if there was a first element in the container. 65 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 66 | // Modifies the state of the iterator. 67 | func (iterator *Iterator[T]) First() bool { 68 | iterator.Begin() 69 | return iterator.Next() 70 | } 71 | -------------------------------------------------------------------------------- /lists/singlylinkedlist/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package singlylinkedlist 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | ) 12 | 13 | func assertSerializationImplementation() { 14 | var _ containers.JSONSerializer = (*List[string])(nil) 15 | var _ containers.JSONDeserializer = (*List[string])(nil) 16 | } 17 | 18 | // ToJSON outputs the JSON representation of list's elements. 19 | func (list *List[T]) ToJSON() ([]byte, error) { 20 | return json.Marshal(list.Values()) 21 | } 22 | 23 | // FromJSON populates list's elements from the input JSON representation. 24 | func (list *List[T]) FromJSON(data []byte) error { 25 | elements := []T{} 26 | err := json.Unmarshal(data, &elements) 27 | if err == nil { 28 | list.Clear() 29 | list.Add(elements...) 30 | } 31 | return err 32 | } 33 | -------------------------------------------------------------------------------- /maps/hashbidimap/hashbidimap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package hashbidimap implements a bidirectional map backed by two hashmaps. 6 | // 7 | // A bidirectional map, or hash bag, is an associative data structure in which the (key,value) pairs form a one-to-one correspondence. 8 | // Thus the binary relation is functional in each direction: value can also act as a key to key. 9 | // A pair (a,b) thus provides a unique coupling between 'a' and 'b' so that 'b' can be found when 'a' is used as a key and 'a' can be found when 'b' is used as a key. 10 | // 11 | // Elements are unordered in the map. 12 | // 13 | // Structure is not thread safe. 14 | // 15 | // Reference: https://en.wikipedia.org/wiki/Bidirectional_map 16 | package hashbidimap 17 | 18 | import ( 19 | "fmt" 20 | 21 | "github.com/daichi-m/go18ds/maps" 22 | "github.com/daichi-m/go18ds/maps/hashmap" 23 | ) 24 | 25 | func assertMapImplementation() { 26 | var _ maps.BidiMap[string, string] = (*Map[string, string])(nil) 27 | } 28 | 29 | // Map holds the elements in two hashmaps. 30 | type Map[K comparable, V comparable] struct { 31 | forwardMap hashmap.Map[K, V] 32 | inverseMap hashmap.Map[V, K] 33 | } 34 | 35 | // New instantiates a bidirectional map. 36 | func New[K comparable, V comparable]() *Map[K, V] { 37 | return &Map[K, V]{*hashmap.New[K, V](), *hashmap.New[V, K]()} 38 | } 39 | 40 | // Put inserts element into the map. 41 | func (m *Map[K, V]) Put(key K, value V) { 42 | if valueByKey, ok := m.forwardMap.Get(key); ok { 43 | m.inverseMap.Remove(valueByKey) 44 | } 45 | if keyByValue, ok := m.inverseMap.Get(value); ok { 46 | m.forwardMap.Remove(keyByValue) 47 | } 48 | m.forwardMap.Put(key, value) 49 | m.inverseMap.Put(value, key) 50 | } 51 | 52 | // Get searches the element in the map by key and returns its value or nil if key is not found in map. 53 | // Second return parameter is true if key was found, otherwise false. 54 | func (m *Map[K, V]) Get(key K) (value V, found bool) { 55 | return m.forwardMap.Get(key) 56 | } 57 | 58 | // GetKey searches the element in the map by value and returns its key or nil if value is not found in map. 59 | // Second return parameter is true if value was found, otherwise false. 60 | func (m *Map[K, V]) GetKey(value V) (key K, found bool) { 61 | return m.inverseMap.Get(value) 62 | } 63 | 64 | // Remove removes the element from the map by key. 65 | func (m *Map[K, V]) Remove(key K) { 66 | if value, found := m.forwardMap.Get(key); found { 67 | m.forwardMap.Remove(key) 68 | m.inverseMap.Remove(value) 69 | } 70 | } 71 | 72 | // Empty returns true if map does not contain any elements 73 | func (m *Map[K, V]) Empty() bool { 74 | return m.Size() == 0 75 | } 76 | 77 | // Size returns number of elements in the map. 78 | func (m *Map[K, V]) Size() int { 79 | return m.forwardMap.Size() 80 | } 81 | 82 | // Keys returns all keys (random order). 83 | func (m *Map[K, V]) Keys() []K { 84 | return m.forwardMap.Keys() 85 | } 86 | 87 | // Values returns all values (random order). 88 | func (m *Map[K, V]) Values() []V { 89 | return m.inverseMap.Keys() 90 | } 91 | 92 | // Clear removes all elements from the map. 93 | func (m *Map[K, V]) Clear() { 94 | m.forwardMap.Clear() 95 | m.inverseMap.Clear() 96 | } 97 | 98 | // String returns a string representation of container 99 | func (m *Map[K, V]) String() string { 100 | str := "HashBidiMap\n" 101 | str += fmt.Sprintf("%v", m.forwardMap) 102 | return str 103 | } 104 | -------------------------------------------------------------------------------- /maps/hashbidimap/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hashbidimap 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | ) 12 | 13 | func assertSerializationImplementation() { 14 | var _ containers.JSONSerializer = (*Map[string, string])(nil) 15 | var _ containers.JSONDeserializer = (*Map[string, string])(nil) 16 | } 17 | 18 | // ToJSON outputs the JSON representation of the map. 19 | func (m *Map[K, V]) ToJSON() ([]byte, error) { 20 | return m.forwardMap.ToJSON() 21 | } 22 | 23 | // FromJSON populates the map from the input JSON representation. 24 | func (m *Map[K, V]) FromJSON(data []byte) error { 25 | elements := make(map[K]V) 26 | err := json.Unmarshal(data, &elements) 27 | if err == nil { 28 | m.Clear() 29 | for key, value := range elements { 30 | m.Put(key, value) 31 | } 32 | } 33 | return err 34 | } 35 | -------------------------------------------------------------------------------- /maps/hashmap/hashmap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package hashmap implements a map backed by a hash table. 6 | // 7 | // Elements are unordered in the map. 8 | // 9 | // Structure is not thread safe. 10 | // 11 | // Reference: http://en.wikipedia.org/wiki/Associative_array 12 | package hashmap 13 | 14 | import ( 15 | "fmt" 16 | 17 | "github.com/daichi-m/go18ds/maps" 18 | ) 19 | 20 | func assertMapImplementation() { 21 | var _ maps.Map[int, string] = (*Map[int, string])(nil) 22 | } 23 | 24 | // Map holds the elements in go's native map 25 | type Map[K comparable, V any] struct { 26 | m map[K]V 27 | } 28 | 29 | // New instantiates a hash map. 30 | func New[K comparable, V any]() *Map[K, V] { 31 | return &Map[K, V]{m: make(map[K]V)} 32 | } 33 | 34 | // Put inserts element into the map. 35 | func (m *Map[K, V]) Put(key K, value V) { 36 | m.m[key] = value 37 | } 38 | 39 | // Get searches the element in the map by key and returns its value or nil if key is not found in map. 40 | // Second return parameter is true if key was found, otherwise false. 41 | func (m *Map[K, V]) Get(key K) (value V, found bool) { 42 | value, found = m.m[key] 43 | return 44 | } 45 | 46 | // Remove removes the element from the map by key. 47 | func (m *Map[K, V]) Remove(key K) { 48 | delete(m.m, key) 49 | } 50 | 51 | // Empty returns true if map does not contain any elements 52 | func (m *Map[K, V]) Empty() bool { 53 | return m.Size() == 0 54 | } 55 | 56 | // Size returns number of elements in the map. 57 | func (m *Map[K, V]) Size() int { 58 | return len(m.m) 59 | } 60 | 61 | // Keys returns all keys (random order). 62 | func (m *Map[K, V]) Keys() []K { 63 | keys := make([]K, m.Size()) 64 | count := 0 65 | for key := range m.m { 66 | keys[count] = key 67 | count++ 68 | } 69 | return keys 70 | } 71 | 72 | // Values returns all values (random order). 73 | func (m *Map[K, V]) Values() []V { 74 | values := make([]V, m.Size()) 75 | count := 0 76 | for _, value := range m.m { 77 | values[count] = value 78 | count++ 79 | } 80 | return values 81 | } 82 | 83 | // Clear removes all elements from the map. 84 | func (m *Map[K, V]) Clear() { 85 | m.m = make(map[K]V) 86 | } 87 | 88 | // String returns a string representation of container 89 | func (m *Map[K, V]) String() string { 90 | str := "HashMap\n" 91 | str += fmt.Sprintf("%v", m.m) 92 | return str 93 | } 94 | -------------------------------------------------------------------------------- /maps/hashmap/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hashmap 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | "github.com/daichi-m/go18ds/utils" 12 | ) 13 | 14 | func assertSerializationImplementation() { 15 | var _ containers.JSONSerializer = (*Map[string, string])(nil) 16 | var _ containers.JSONDeserializer = (*Map[string, string])(nil) 17 | } 18 | 19 | // ToJSON outputs the JSON representation of the map. 20 | func (m *Map[K, V]) ToJSON() ([]byte, error) { 21 | elements := make(map[string]V) 22 | for key, value := range m.m { 23 | elements[utils.ToString(key)] = value 24 | } 25 | return json.Marshal(&elements) 26 | } 27 | 28 | // FromJSON populates the map from the input JSON representation. 29 | func (m *Map[K, V]) FromJSON(data []byte) error { 30 | elements := make(map[K]V) 31 | err := json.Unmarshal(data, &elements) 32 | if err == nil { 33 | m.Clear() 34 | for key, value := range elements { 35 | m.m[key] = value 36 | } 37 | } 38 | return err 39 | } 40 | -------------------------------------------------------------------------------- /maps/linkedhashmap/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package linkedhashmap 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertEnumerableImplementation() { 10 | var _ containers.EnumerableWithKey[string, int] = (*Map[string, int])(nil) 11 | } 12 | 13 | // Each calls the given function once for each element, passing that element's key and value. 14 | func (m *Map[K, V]) Each(f func(key K, value V)) { 15 | iterator := m.Iterator() 16 | for iterator.Next() { 17 | f(iterator.Key(), iterator.Value()) 18 | } 19 | } 20 | 21 | // Map invokes the given function once for each element and returns a container 22 | // containing the values returned by the given function as key/value pairs. 23 | func (m *Map[K, V]) Map(f func(key K, value V) (K, V)) *Map[K, V] { 24 | newMap := New[K, V]() 25 | iterator := m.Iterator() 26 | for iterator.Next() { 27 | key2, value2 := f(iterator.Key(), iterator.Value()) 28 | newMap.Put(key2, value2) 29 | } 30 | return newMap 31 | } 32 | 33 | // Select returns a new container containing all elements for which the given function returns a true value. 34 | func (m *Map[K, V]) Select(f func(key K, value V) bool) *Map[K, V] { 35 | newMap := New[K, V]() 36 | iterator := m.Iterator() 37 | for iterator.Next() { 38 | if f(iterator.Key(), iterator.Value()) { 39 | newMap.Put(iterator.Key(), iterator.Value()) 40 | } 41 | } 42 | return newMap 43 | } 44 | 45 | // Any passes each element of the container to the given function and 46 | // returns true if the function ever returns true for any element. 47 | func (m *Map[K, V]) Any(f func(key K, value V) bool) bool { 48 | iterator := m.Iterator() 49 | for iterator.Next() { 50 | if f(iterator.Key(), iterator.Value()) { 51 | return true 52 | } 53 | } 54 | return false 55 | } 56 | 57 | // All passes each element of the container to the given function and 58 | // returns true if the function returns true for all elements. 59 | func (m *Map[K, V]) All(f func(key K, value V) bool) bool { 60 | iterator := m.Iterator() 61 | for iterator.Next() { 62 | if !f(iterator.Key(), iterator.Value()) { 63 | return false 64 | } 65 | } 66 | return true 67 | } 68 | 69 | // Find passes each element of the container to the given function and returns 70 | // the first (key,value) for which the function is true or nil,nil otherwise if no element 71 | // matches the criteria. 72 | func (m *Map[K, V]) Find(f func(key K, value V) bool) (K, V) { 73 | iterator := m.Iterator() 74 | for iterator.Next() { 75 | if f(iterator.Key(), iterator.Value()) { 76 | return iterator.Key(), iterator.Value() 77 | } 78 | } 79 | return *new(K), *new(V) 80 | } 81 | -------------------------------------------------------------------------------- /maps/linkedhashmap/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package linkedhashmap 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/containers" 9 | "github.com/daichi-m/go18ds/lists/doublylinkedlist" 10 | ) 11 | 12 | func assertIteratorImplementation() { 13 | var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil) 14 | } 15 | 16 | // Iterator holding the iterator's state 17 | type Iterator[K comparable, V any] struct { 18 | iterator doublylinkedlist.Iterator[K] 19 | table map[K]V 20 | } 21 | 22 | // Iterator returns a stateful iterator whose elements are key/value pairs. 23 | func (m *Map[K, V]) Iterator() Iterator[K, V] { 24 | return Iterator[K, V]{ 25 | iterator: m.ordering.Iterator(), 26 | table: m.table} 27 | } 28 | 29 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 30 | // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). 31 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 32 | // Modifies the state of the iterator. 33 | func (iterator *Iterator[K, V]) Next() bool { 34 | return iterator.iterator.Next() 35 | } 36 | 37 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 38 | // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). 39 | // Modifies the state of the iterator. 40 | func (iterator *Iterator[K, V]) Prev() bool { 41 | return iterator.iterator.Prev() 42 | } 43 | 44 | // Value returns the current element's value. 45 | // Does not modify the state of the iterator. 46 | func (iterator *Iterator[K, V]) Value() V { 47 | key := iterator.iterator.Value() 48 | return iterator.table[key] 49 | } 50 | 51 | // Key returns the current element's key. 52 | // Does not modify the state of the iterator. 53 | func (iterator *Iterator[K, V]) Key() K { 54 | return iterator.iterator.Value() 55 | } 56 | 57 | // Begin resets the iterator to its initial state (one-before-first) 58 | // Call Next() to fetch the first element if any. 59 | func (iterator *Iterator[K, V]) Begin() { 60 | iterator.iterator.Begin() 61 | } 62 | 63 | // End moves the iterator past the last element (one-past-the-end). 64 | // Call Prev() to fetch the last element if any. 65 | func (iterator *Iterator[K, V]) End() { 66 | iterator.iterator.End() 67 | } 68 | 69 | // First moves the iterator to the first element and returns true if there was a first element in the container. 70 | // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). 71 | // Modifies the state of the iterator 72 | func (iterator *Iterator[K, V]) First() bool { 73 | return iterator.iterator.First() 74 | } 75 | 76 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 77 | // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). 78 | // Modifies the state of the iterator. 79 | func (iterator *Iterator[K, V]) Last() bool { 80 | return iterator.iterator.Last() 81 | } 82 | -------------------------------------------------------------------------------- /maps/linkedhashmap/linkedhashmap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package linkedhashmap is a map that preserves insertion-order. 6 | // 7 | // It is backed by a hash table to store values and doubly-linked list to store ordering. 8 | // 9 | // Structure is not thread safe. 10 | // 11 | // Reference: http://en.wikipedia.org/wiki/Associative_array 12 | package linkedhashmap 13 | 14 | import ( 15 | "fmt" 16 | "strings" 17 | 18 | "github.com/daichi-m/go18ds/lists/doublylinkedlist" 19 | "github.com/daichi-m/go18ds/maps" 20 | ) 21 | 22 | func assertMapImplementation() { 23 | var _ maps.Map[string, string] = (*Map[string, string])(nil) 24 | } 25 | 26 | // Map holds the elements in a regular hash table, and uses doubly-linked list to store key ordering. 27 | type Map[K comparable, V comparable] struct { 28 | table map[K]V 29 | ordering *doublylinkedlist.List[K] 30 | } 31 | 32 | // New instantiates a linked-hash-map. 33 | func New[K comparable, V comparable]() *Map[K, V] { 34 | return &Map[K, V]{ 35 | table: make(map[K]V), 36 | ordering: doublylinkedlist.New[K](), 37 | } 38 | } 39 | 40 | // Put inserts key-value pair into the map. 41 | // Key should adhere to the comparator's type assertion, otherwise method panics. 42 | func (m *Map[K, V]) Put(key K, value V) { 43 | if _, contains := m.table[key]; !contains { 44 | m.ordering.Append(key) 45 | } 46 | m.table[key] = value 47 | } 48 | 49 | // Get searches the element in the map by key and returns its value or nil if key is not found in tree. 50 | // Second return parameter is true if key was found, otherwise false. 51 | // Key should adhere to the comparator's type assertion, otherwise method panics. 52 | func (m *Map[K, V]) Get(key K) (value V, found bool) { 53 | value, found = m.table[key] 54 | return 55 | } 56 | 57 | // Remove removes the element from the map by key. 58 | // Key should adhere to the comparator's type assertion, otherwise method panics. 59 | func (m *Map[K, V]) Remove(key K) { 60 | if _, contains := m.table[key]; contains { 61 | delete(m.table, key) 62 | index := m.ordering.IndexOf(key) 63 | m.ordering.Remove(index) 64 | } 65 | } 66 | 67 | // Empty returns true if map does not contain any elements 68 | func (m *Map[K, V]) Empty() bool { 69 | return m.Size() == 0 70 | } 71 | 72 | // Size returns number of elements in the map. 73 | func (m *Map[K, V]) Size() int { 74 | return m.ordering.Size() 75 | } 76 | 77 | // Keys returns all keys in-order 78 | func (m *Map[K, V]) Keys() []K { 79 | return m.ordering.Values() 80 | } 81 | 82 | // Values returns all values in-order based on the key. 83 | func (m *Map[K, V]) Values() []V { 84 | values := make([]V, m.Size()) 85 | count := 0 86 | it := m.Iterator() 87 | for it.Next() { 88 | values[count] = it.Value() 89 | count++ 90 | } 91 | return values 92 | } 93 | 94 | // Clear removes all elements from the map. 95 | func (m *Map[K, V]) Clear() { 96 | m.table = make(map[K]V) 97 | m.ordering.Clear() 98 | } 99 | 100 | // String returns a string representation of container 101 | func (m *Map[K, V]) String() string { 102 | str := "LinkedHashMap\nmap[" 103 | it := m.Iterator() 104 | for it.Next() { 105 | str += fmt.Sprintf("%v:%v ", it.Key(), it.Value()) 106 | } 107 | return strings.TrimRight(str, " ") + "]" 108 | } 109 | -------------------------------------------------------------------------------- /maps/linkedhashmap/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package linkedhashmap 6 | 7 | import ( 8 | "bytes" 9 | "encoding/json" 10 | 11 | "github.com/daichi-m/go18ds/containers" 12 | "github.com/daichi-m/go18ds/utils" 13 | ) 14 | 15 | func assertSerializationImplementation() { 16 | var _ containers.JSONSerializer = (*Map[string, string])(nil) 17 | var _ containers.JSONDeserializer = (*Map[string, string])(nil) 18 | } 19 | 20 | // ToJSON outputs the JSON representation of map. 21 | func (m *Map[K, V]) ToJSON() ([]byte, error) { 22 | var b []byte 23 | buf := bytes.NewBuffer(b) 24 | 25 | buf.WriteRune('{') 26 | 27 | it := m.Iterator() 28 | lastIndex := m.Size() - 1 29 | index := 0 30 | 31 | for it.Next() { 32 | km, err := json.Marshal(it.Key()) 33 | if err != nil { 34 | return nil, err 35 | } 36 | buf.Write(km) 37 | 38 | buf.WriteRune(':') 39 | 40 | vm, err := json.Marshal(it.Value()) 41 | if err != nil { 42 | return nil, err 43 | } 44 | buf.Write(vm) 45 | 46 | if index != lastIndex { 47 | buf.WriteRune(',') 48 | } 49 | 50 | index++ 51 | } 52 | 53 | buf.WriteRune('}') 54 | 55 | return buf.Bytes(), nil 56 | } 57 | 58 | // FromJSON populates map from the input JSON representation. 59 | //func (m *Map) FromJSON(data []byte) error { 60 | // elements := make(map[string]interface{}) 61 | // err := json.Unmarshal(data, &elements) 62 | // if err == nil { 63 | // m.Clear() 64 | // for key, value := range elements { 65 | // m.Put(key, value) 66 | // } 67 | // } 68 | // return err 69 | //} 70 | 71 | // FromJSON populates map from the input JSON representation. 72 | func (m *Map[string, V]) FromJSON(data []byte) error { 73 | elements := make(map[string]V) 74 | err := json.Unmarshal(data, &elements) 75 | if err != nil { 76 | return err 77 | } 78 | 79 | index := make(map[string]int) 80 | var keys []string 81 | for key := range elements { 82 | keys = append(keys, key) 83 | esc, _ := json.Marshal(key) 84 | index[key] = bytes.Index(data, esc) 85 | } 86 | 87 | byIndex := func(key1, key2 string) int { 88 | index1 := index[key1] 89 | index2 := index[key2] 90 | return index1 - index2 91 | } 92 | 93 | utils.Sort(keys, byIndex) 94 | 95 | m.Clear() 96 | 97 | for _, key := range keys { 98 | m.Put(key, elements[key]) 99 | } 100 | 101 | return nil 102 | } 103 | -------------------------------------------------------------------------------- /maps/maps.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package maps provides an abstract Map interface. 6 | // 7 | // In computer science, an associative array, map, symbol table, or dictionary is an abstract data type composed of a collection of (key, value) pairs, such that each possible key appears just once in the collection. 8 | // 9 | // Operations associated with this data type allow: 10 | // - the addition of a pair to the collection 11 | // - the removal of a pair from the collection 12 | // - the modification of an existing pair 13 | // - the lookup of a value associated with a particular key 14 | // 15 | // Reference: https://en.wikipedia.org/wiki/Associative_array 16 | package maps 17 | 18 | import "github.com/daichi-m/go18ds/containers" 19 | 20 | // Map interface that all maps implement 21 | type Map[K comparable, V any] interface { 22 | Put(key K, value V) 23 | Get(key K) (value V, found bool) 24 | Remove(key K) 25 | Keys() []K 26 | 27 | containers.Container[V] 28 | // Empty() bool 29 | // Size() int 30 | // Clear() 31 | // Values() []interface{} 32 | } 33 | 34 | // BidiMap interface that all bidirectional maps implement (extends the Map interface) 35 | type BidiMap[K comparable, V any] interface { 36 | GetKey(value V) (key K, found bool) 37 | 38 | Map[K, V] 39 | } 40 | -------------------------------------------------------------------------------- /maps/treebidimap/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treebidimap 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertEnumerableImplementation() { 10 | var _ containers.EnumerableWithKey[string, string] = (*Map[string, string])(nil) 11 | } 12 | 13 | // Each calls the given function once for each element, passing that element's key and value. 14 | func (m *Map[K, V]) Each(f func(key K, value V)) { 15 | iterator := m.Iterator() 16 | for iterator.Next() { 17 | f(iterator.Key(), iterator.Value()) 18 | } 19 | } 20 | 21 | // Map invokes the given function once for each element and returns a container 22 | // containing the values returned by the given function as key/value pairs. 23 | func (m *Map[K, V]) Map(f func(key1 K, value1 V) (K, V)) *Map[K, V] { 24 | newMap := NewWith(m.keyComparator, m.valueComparator) 25 | iterator := m.Iterator() 26 | for iterator.Next() { 27 | key2, value2 := f(iterator.Key(), iterator.Value()) 28 | newMap.Put(key2, value2) 29 | } 30 | return newMap 31 | } 32 | 33 | // Select returns a new container containing all elements for which the given function returns a true value. 34 | func (m *Map[K, V]) Select(f func(key K, value V) bool) *Map[K, V] { 35 | newMap := NewWith(m.keyComparator, m.valueComparator) 36 | iterator := m.Iterator() 37 | for iterator.Next() { 38 | if f(iterator.Key(), iterator.Value()) { 39 | newMap.Put(iterator.Key(), iterator.Value()) 40 | } 41 | } 42 | return newMap 43 | } 44 | 45 | // Any passes each element of the container to the given function and 46 | // returns true if the function ever returns true for any element. 47 | func (m *Map[K, V]) Any(f func(key K, value V) bool) bool { 48 | iterator := m.Iterator() 49 | for iterator.Next() { 50 | if f(iterator.Key(), iterator.Value()) { 51 | return true 52 | } 53 | } 54 | return false 55 | } 56 | 57 | // All passes each element of the container to the given function and 58 | // returns true if the function returns true for all elements. 59 | func (m *Map[K, V]) All(f func(key K, value V) bool) bool { 60 | iterator := m.Iterator() 61 | for iterator.Next() { 62 | if !f(iterator.Key(), iterator.Value()) { 63 | return false 64 | } 65 | } 66 | return true 67 | } 68 | 69 | // Find passes each element of the container to the given function and returns 70 | // the first (key,value) for which the function is true or nil,nil otherwise if no element 71 | // matches the criteria. 72 | func (m *Map[K, V]) Find(f func(key K, value V) bool) (K, V) { 73 | iterator := m.Iterator() 74 | for iterator.Next() { 75 | if f(iterator.Key(), iterator.Value()) { 76 | return iterator.Key(), iterator.Value() 77 | } 78 | } 79 | return *new(K), *new(V) 80 | } 81 | -------------------------------------------------------------------------------- /maps/treebidimap/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treebidimap 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/containers" 9 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 10 | ) 11 | 12 | func assertIteratorImplementation() { 13 | var _ containers.ReverseIteratorWithKey[string, string] = (*Iterator[string, string])(nil) 14 | } 15 | 16 | // Iterator holding the iterator's state 17 | type Iterator[K comparable, V comparable] struct { 18 | iterator rbt.Iterator[K, *data[K, V]] 19 | } 20 | 21 | // Iterator returns a stateful iterator whose elements are key/value pairs. 22 | func (m *Map[K, V]) Iterator() Iterator[K, V] { 23 | return Iterator[K, V]{iterator: m.forwardMap.Iterator()} 24 | } 25 | 26 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 27 | // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). 28 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 29 | // Modifies the state of the iterator. 30 | func (iterator *Iterator[K, V]) Next() bool { 31 | return iterator.iterator.Next() 32 | } 33 | 34 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 35 | // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). 36 | // Modifies the state of the iterator. 37 | func (iterator *Iterator[K, V]) Prev() bool { 38 | return iterator.iterator.Prev() 39 | } 40 | 41 | // Value returns the current element's value. 42 | // Does not modify the state of the iterator. 43 | func (iterator *Iterator[K, V]) Value() V { 44 | return iterator.iterator.Value().value 45 | } 46 | 47 | // Key returns the current element's key. 48 | // Does not modify the state of the iterator. 49 | func (iterator *Iterator[K, V]) Key() K { 50 | return iterator.iterator.Key() 51 | } 52 | 53 | // Begin resets the iterator to its initial state (one-before-first) 54 | // Call Next() to fetch the first element if any. 55 | func (iterator *Iterator[K, V]) Begin() { 56 | iterator.iterator.Begin() 57 | } 58 | 59 | // End moves the iterator past the last element (one-past-the-end). 60 | // Call Prev() to fetch the last element if any. 61 | func (iterator *Iterator[K, V]) End() { 62 | iterator.iterator.End() 63 | } 64 | 65 | // First moves the iterator to the first element and returns true if there was a first element in the container. 66 | // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). 67 | // Modifies the state of the iterator 68 | func (iterator *Iterator[K, V]) First() bool { 69 | return iterator.iterator.First() 70 | } 71 | 72 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 73 | // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). 74 | // Modifies the state of the iterator. 75 | func (iterator *Iterator[K, V]) Last() bool { 76 | return iterator.iterator.Last() 77 | } 78 | -------------------------------------------------------------------------------- /maps/treebidimap/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treebidimap 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | "github.com/daichi-m/go18ds/utils" 12 | ) 13 | 14 | func assertSerializationImplementation() { 15 | var _ containers.JSONSerializer = (*Map[string, string])(nil) 16 | var _ containers.JSONDeserializer = (*Map[string, string])(nil) 17 | } 18 | 19 | // ToJSON outputs the JSON representation of the map. 20 | func (m *Map[K, V]) ToJSON() ([]byte, error) { 21 | elements := make(map[string]V) 22 | it := m.Iterator() 23 | for it.Next() { 24 | elements[utils.ToString(it.Key())] = it.Value() 25 | } 26 | return json.Marshal(&elements) 27 | } 28 | 29 | // FromJSON populates the map from the input JSON representation. 30 | func (m *Map[string, V]) FromJSON(data []byte) error { 31 | elements := make(map[string]V) 32 | err := json.Unmarshal(data, &elements) 33 | if err == nil { 34 | m.Clear() 35 | for key, value := range elements { 36 | m.Put(key, value) 37 | } 38 | } 39 | return err 40 | } 41 | -------------------------------------------------------------------------------- /maps/treebidimap/treebidimap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package treebidimap implements a bidirectional map backed by two red-black tree. 6 | // 7 | // This structure guarantees that the map will be in both ascending key and value order. 8 | // 9 | // Other than key and value ordering, the goal with this structure is to avoid duplication of elements, which can be significant if contained elements are large. 10 | // 11 | // A bidirectional map, or hash bag, is an associative data structure in which the (key,value) pairs form a one-to-one correspondence. 12 | // Thus the binary relation is functional in each direction: value can also act as a key to key. 13 | // A pair (a,b) thus provides a unique coupling between 'a' and 'b' so that 'b' can be found when 'a' is used as a key and 'a' can be found when 'b' is used as a key. 14 | // 15 | // Structure is not thread safe. 16 | // 17 | // Reference: https://en.wikipedia.org/wiki/Bidirectional_map 18 | package treebidimap 19 | 20 | import ( 21 | "fmt" 22 | "strings" 23 | 24 | "github.com/daichi-m/go18ds/maps" 25 | "github.com/daichi-m/go18ds/trees/redblacktree" 26 | "github.com/daichi-m/go18ds/utils" 27 | ) 28 | 29 | func assertMapImplementation() { 30 | var _ maps.BidiMap[string, string] = (*Map[string, string])(nil) 31 | } 32 | 33 | // Map holds the elements in two red-black trees. 34 | type Map[K comparable, V comparable] struct { 35 | forwardMap redblacktree.Tree[K, *data[K, V]] 36 | inverseMap redblacktree.Tree[V, *data[K, V]] 37 | keyComparator utils.Comparator[K] 38 | valueComparator utils.Comparator[V] 39 | } 40 | 41 | type data[K comparable, V comparable] struct { 42 | key K 43 | value V 44 | } 45 | 46 | // NewWith instantiates a bidirectional map. 47 | func NewWith[K comparable, V comparable](keyComparator utils.Comparator[K], 48 | valueComparator utils.Comparator[V]) *Map[K, V] { 49 | return &Map[K, V]{ 50 | forwardMap: *redblacktree.NewWith[K, *data[K, V]](keyComparator), 51 | inverseMap: *redblacktree.NewWith[V, *data[K, V]](valueComparator), 52 | keyComparator: keyComparator, 53 | valueComparator: valueComparator, 54 | } 55 | } 56 | 57 | // NewWithIntComparators instantiates a bidirectional map with the IntComparator for key and value, i.e. keys and values are of type int. 58 | func NewWithIntComparators() *Map[int, int] { 59 | return NewWith(utils.NumberComparator[int], utils.NumberComparator[int]) 60 | } 61 | 62 | // NewWithStringComparators instantiates a bidirectional map with the StringComparator for key and value, i.e. keys and values are of type string. 63 | func NewWithStringComparators() *Map[string, string] { 64 | return NewWith(utils.StringComparator, utils.StringComparator) 65 | } 66 | 67 | // Put inserts element into the map. 68 | func (m *Map[K, V]) Put(key K, value V) { 69 | if d, ok := m.forwardMap.Get(key); ok { 70 | m.inverseMap.Remove(d.value) 71 | } 72 | if d, ok := m.inverseMap.Get(value); ok { 73 | m.forwardMap.Remove(d.key) 74 | } 75 | d := &data[K, V]{key: key, value: value} 76 | m.forwardMap.Put(key, d) 77 | m.inverseMap.Put(value, d) 78 | } 79 | 80 | // Get searches the element in the map by key and returns its value or nil if key is not found in map. 81 | // Second return parameter is true if key was found, otherwise false. 82 | func (m *Map[K, V]) Get(key K) (value V, found bool) { 83 | if d, ok := m.forwardMap.Get(key); ok { 84 | return d.value, true 85 | } 86 | return *new(V), false 87 | } 88 | 89 | // GetKey searches the element in the map by value and returns its key or nil if value is not found in map. 90 | // Second return parameter is true if value was found, otherwise false. 91 | func (m *Map[K, V]) GetKey(value V) (key K, found bool) { 92 | if d, ok := m.inverseMap.Get(value); ok { 93 | return d.key, true 94 | } 95 | return *new(K), false 96 | } 97 | 98 | // Remove removes the element from the map by key. 99 | func (m *Map[K, V]) Remove(key K) { 100 | if d, found := m.forwardMap.Get(key); found { 101 | m.forwardMap.Remove(key) 102 | m.inverseMap.Remove(d.value) 103 | } 104 | } 105 | 106 | // Empty returns true if map does not contain any elements 107 | func (m *Map[K, V]) Empty() bool { 108 | return m.Size() == 0 109 | } 110 | 111 | // Size returns number of elements in the map. 112 | func (m *Map[K, V]) Size() int { 113 | return m.forwardMap.Size() 114 | } 115 | 116 | // Keys returns all keys (ordered). 117 | func (m *Map[K, V]) Keys() []K { 118 | return m.forwardMap.Keys() 119 | } 120 | 121 | // Values returns all values (ordered). 122 | func (m *Map[K, V]) Values() []V { 123 | return m.inverseMap.Keys() 124 | } 125 | 126 | // Clear removes all elements from the map. 127 | func (m *Map[K, V]) Clear() { 128 | m.forwardMap.Clear() 129 | m.inverseMap.Clear() 130 | } 131 | 132 | // String returns a string representation of container 133 | func (m *Map[K, V]) String() string { 134 | str := "TreeBidiMap\nmap[" 135 | it := m.Iterator() 136 | for it.Next() { 137 | str += fmt.Sprintf("%v:%v ", it.Key(), it.Value()) 138 | } 139 | return strings.TrimRight(str, " ") + "]" 140 | } 141 | -------------------------------------------------------------------------------- /maps/treemap/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treemap 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/containers" 9 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 10 | ) 11 | 12 | func assertEnumerableImplementation() { 13 | var _ containers.EnumerableWithKey[string, string] = (*Map[string, string])(nil) 14 | } 15 | 16 | // Each calls the given function once for each element, passing that element's key and value. 17 | func (m *Map[K, V]) Each(f func(key K, value V)) { 18 | iterator := m.Iterator() 19 | for iterator.Next() { 20 | f(iterator.Key(), iterator.Value()) 21 | } 22 | } 23 | 24 | // Map invokes the given function once for each element and returns a container 25 | // containing the values returned by the given function as key/value pairs. 26 | func (m *Map[K, V]) Map(f func(key K, value V) (K, V)) *Map[K, V] { 27 | newMap := &Map[K, V]{tree: rbt.NewWith[K, V](m.tree.Comparator)} 28 | iterator := m.Iterator() 29 | for iterator.Next() { 30 | key2, value2 := f(iterator.Key(), iterator.Value()) 31 | newMap.Put(key2, value2) 32 | } 33 | return newMap 34 | } 35 | 36 | // Select returns a new container containing all elements for which the given function returns a true value. 37 | func (m *Map[K, V]) Select(f func(key K, value V) bool) *Map[K, V] { 38 | newMap := &Map[K, V]{tree: rbt.NewWith[K, V](m.tree.Comparator)} 39 | iterator := m.Iterator() 40 | for iterator.Next() { 41 | if f(iterator.Key(), iterator.Value()) { 42 | newMap.Put(iterator.Key(), iterator.Value()) 43 | } 44 | } 45 | return newMap 46 | } 47 | 48 | // Any passes each element of the container to the given function and 49 | // returns true if the function ever returns true for any element. 50 | func (m *Map[K, V]) Any(f func(key K, value V) bool) bool { 51 | iterator := m.Iterator() 52 | for iterator.Next() { 53 | if f(iterator.Key(), iterator.Value()) { 54 | return true 55 | } 56 | } 57 | return false 58 | } 59 | 60 | // All passes each element of the container to the given function and 61 | // returns true if the function returns true for all elements. 62 | func (m *Map[K, V]) All(f func(key K, value V) bool) bool { 63 | iterator := m.Iterator() 64 | for iterator.Next() { 65 | if !f(iterator.Key(), iterator.Value()) { 66 | return false 67 | } 68 | } 69 | return true 70 | } 71 | 72 | // Find passes each element of the container to the given function and returns 73 | // the first (key,value) for which the function is true or nil,nil otherwise if no element 74 | // matches the criteria. 75 | func (m *Map[K, V]) Find(f func(key K, value V) bool) (K, V) { 76 | iterator := m.Iterator() 77 | for iterator.Next() { 78 | if f(iterator.Key(), iterator.Value()) { 79 | return iterator.Key(), iterator.Value() 80 | } 81 | } 82 | return *new(K), *new(V) 83 | } 84 | -------------------------------------------------------------------------------- /maps/treemap/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treemap 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/containers" 9 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 10 | ) 11 | 12 | func assertIteratorImplementation() { 13 | var _ containers.ReverseIteratorWithKey[string, string] = (*Iterator[string, string])(nil) 14 | } 15 | 16 | // Iterator holding the iterator's state 17 | type Iterator[K comparable, V comparable] struct { 18 | iterator rbt.Iterator[K, V] 19 | } 20 | 21 | // Iterator returns a stateful iterator whose elements are key/value pairs. 22 | func (m *Map[K, V]) Iterator() Iterator[K, V] { 23 | return Iterator[K, V]{iterator: m.tree.Iterator()} 24 | } 25 | 26 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 27 | // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). 28 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 29 | // Modifies the state of the iterator. 30 | func (iterator *Iterator[K, V]) Next() bool { 31 | return iterator.iterator.Next() 32 | } 33 | 34 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 35 | // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). 36 | // Modifies the state of the iterator. 37 | func (iterator *Iterator[K, V]) Prev() bool { 38 | return iterator.iterator.Prev() 39 | } 40 | 41 | // Value returns the current element's value. 42 | // Does not modify the state of the iterator. 43 | func (iterator *Iterator[K, V]) Value() V { 44 | return iterator.iterator.Value() 45 | } 46 | 47 | // Key returns the current element's key. 48 | // Does not modify the state of the iterator. 49 | func (iterator *Iterator[K, V]) Key() K { 50 | return iterator.iterator.Key() 51 | } 52 | 53 | // Begin resets the iterator to its initial state (one-before-first) 54 | // Call Next() to fetch the first element if any. 55 | func (iterator *Iterator[K, V]) Begin() { 56 | iterator.iterator.Begin() 57 | } 58 | 59 | // End moves the iterator past the last element (one-past-the-end). 60 | // Call Prev() to fetch the last element if any. 61 | func (iterator *Iterator[K, V]) End() { 62 | iterator.iterator.End() 63 | } 64 | 65 | // First moves the iterator to the first element and returns true if there was a first element in the container. 66 | // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). 67 | // Modifies the state of the iterator 68 | func (iterator *Iterator[K, V]) First() bool { 69 | return iterator.iterator.First() 70 | } 71 | 72 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 73 | // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). 74 | // Modifies the state of the iterator. 75 | func (iterator *Iterator[K, V]) Last() bool { 76 | return iterator.iterator.Last() 77 | } 78 | -------------------------------------------------------------------------------- /maps/treemap/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treemap 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertSerializationImplementation() { 10 | var _ containers.JSONSerializer = (*Map[string, string])(nil) 11 | var _ containers.JSONDeserializer = (*Map[string, string])(nil) 12 | } 13 | 14 | // ToJSON outputs the JSON representation of the map. 15 | func (m *Map[K, V]) ToJSON() ([]byte, error) { 16 | return m.tree.ToJSON() 17 | } 18 | 19 | // FromJSON populates the map from the input JSON representation. 20 | func (m *Map[K, V]) FromJSON(data []byte) error { 21 | return m.tree.FromJSON(data) 22 | } 23 | -------------------------------------------------------------------------------- /maps/treemap/treemap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package treemap implements a map backed by red-black tree. 6 | // 7 | // Elements are ordered by key in the map. 8 | // 9 | // Structure is not thread safe. 10 | // 11 | // Reference: http://en.wikipedia.org/wiki/Associative_array 12 | package treemap 13 | 14 | import ( 15 | "fmt" 16 | "strings" 17 | 18 | "github.com/daichi-m/go18ds/maps" 19 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 20 | "github.com/daichi-m/go18ds/utils" 21 | ) 22 | 23 | func assertMapImplementation() { 24 | var _ maps.Map[string, string] = (*Map[string, string])(nil) 25 | } 26 | 27 | // Map holds the elements in a red-black tree 28 | type Map[K comparable, V comparable] struct { 29 | tree *rbt.Tree[K, V] 30 | } 31 | 32 | // NewWith instantiates a tree map with the custom comparator. 33 | func NewWith[K comparable, V comparable](comparator utils.Comparator[K]) *Map[K, V] { 34 | return &Map[K, V]{tree: rbt.NewWith[K, V](comparator)} 35 | } 36 | 37 | // NewWithIntComparator instantiates a tree map with the IntComparator, i.e. keys are of type int. 38 | func NewWithIntComparator[V comparable]() *Map[int, V] { 39 | return &Map[int, V]{tree: rbt.NewWithIntComparator[V]()} 40 | } 41 | 42 | // NewWithStringComparator instantiates a tree map with the StringComparator, i.e. keys are of type string. 43 | func NewWithStringComparator[V comparable]() *Map[string, V] { 44 | return &Map[string, V]{tree: rbt.NewWithStringComparator[V]()} 45 | } 46 | 47 | // Put inserts key-value pair into the map. 48 | // Key should adhere to the comparator's type assertion, otherwise method panics. 49 | func (m *Map[K, V]) Put(key K, value V) { 50 | m.tree.Put(key, value) 51 | } 52 | 53 | // Get searches the element in the map by key and returns its value or nil if key is not found in tree. 54 | // Second return parameter is true if key was found, otherwise false. 55 | // Key should adhere to the comparator's type assertion, otherwise method panics. 56 | func (m *Map[K, V]) Get(key K) (value V, found bool) { 57 | return m.tree.Get(key) 58 | } 59 | 60 | // Remove removes the element from the map by key. 61 | // Key should adhere to the comparator's type assertion, otherwise method panics. 62 | func (m *Map[K, V]) Remove(key K) { 63 | m.tree.Remove(key) 64 | } 65 | 66 | // Empty returns true if map does not contain any elements 67 | func (m *Map[K, V]) Empty() bool { 68 | return m.tree.Empty() 69 | } 70 | 71 | // Size returns number of elements in the map. 72 | func (m *Map[K, V]) Size() int { 73 | return m.tree.Size() 74 | } 75 | 76 | // Keys returns all keys in-order 77 | func (m *Map[K, V]) Keys() []K { 78 | return m.tree.Keys() 79 | } 80 | 81 | // Values returns all values in-order based on the key. 82 | func (m *Map[K, V]) Values() []V { 83 | return m.tree.Values() 84 | } 85 | 86 | // Clear removes all elements from the map. 87 | func (m *Map[K, V]) Clear() { 88 | m.tree.Clear() 89 | } 90 | 91 | // Min returns the minimum key and its value from the tree map. 92 | // Returns nil, nil if map is empty. 93 | func (m *Map[K, V]) Min() (key K, value V) { 94 | if node := m.tree.Left(); node != nil { 95 | return node.Key, node.Value 96 | } 97 | return *new(K), *new(V) 98 | } 99 | 100 | // Max returns the maximum key and its value from the tree map. 101 | // Returns nil, nil if map is empty. 102 | func (m *Map[K, V]) Max() (key K, value V) { 103 | if node := m.tree.Right(); node != nil { 104 | return node.Key, node.Value 105 | } 106 | return *new(K), *new(V) 107 | } 108 | 109 | // Floor finds the floor key-value pair for the input key. 110 | // In case that no floor is found, then both returned values will be nil. 111 | // It's generally enough to check the first value (key) for nil, which determines if floor was found. 112 | // 113 | // Floor key is defined as the largest key that is smaller than or equal to the given key. 114 | // A floor key may not be found, either because the map is empty, or because 115 | // all keys in the map are larger than the given key. 116 | // 117 | // Key should adhere to the comparator's type assertion, otherwise method panics. 118 | func (m *Map[K, V]) Floor(key K) (foundKey K, foundValue V) { 119 | node, found := m.tree.Floor(key) 120 | if found { 121 | return node.Key, node.Value 122 | } 123 | return *new(K), *new(V) 124 | } 125 | 126 | // Ceiling finds the ceiling key-value pair for the input key. 127 | // In case that no ceiling is found, then both returned values will be nil. 128 | // It's generally enough to check the first value (key) for nil, which determines if ceiling was found. 129 | // 130 | // Ceiling key is defined as the smallest key that is larger than or equal to the given key. 131 | // A ceiling key may not be found, either because the map is empty, or because 132 | // all keys in the map are smaller than the given key. 133 | // 134 | // Key should adhere to the comparator's type assertion, otherwise method panics. 135 | func (m *Map[K, V]) Ceiling(key K) (foundKey K, foundValue V) { 136 | node, found := m.tree.Ceiling(key) 137 | if found { 138 | return node.Key, node.Value 139 | } 140 | return *new(K), *new(V) 141 | } 142 | 143 | // String returns a string representation of container 144 | func (m *Map[K, V]) String() string { 145 | str := "TreeMap\nmap[" 146 | it := m.Iterator() 147 | for it.Next() { 148 | str += fmt.Sprintf("%v:%v ", it.Key(), it.Value()) 149 | } 150 | return strings.TrimRight(str, " ") + "]" 151 | } 152 | -------------------------------------------------------------------------------- /sets/hashset/hashset.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package hashset implements a set backed by a hash table. 6 | // 7 | // Structure is not thread safe. 8 | // 9 | // References: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29 10 | package hashset 11 | 12 | import ( 13 | "fmt" 14 | "strings" 15 | 16 | "github.com/daichi-m/go18ds/sets" 17 | ) 18 | 19 | func assertSetImplementation() { 20 | var _ sets.Set[string] = (*Set[string])(nil) 21 | } 22 | 23 | // Set holds elements in go's native map 24 | type Set[T comparable] struct { 25 | items map[T]struct{} 26 | } 27 | 28 | var itemExists = struct{}{} 29 | 30 | // New instantiates a new empty set and adds the passed values, if any, to the set 31 | func New[T comparable](values ...T) *Set[T] { 32 | set := &Set[T]{items: make(map[T]struct{})} 33 | if len(values) > 0 { 34 | set.Add(values...) 35 | } 36 | return set 37 | } 38 | 39 | // Add adds the items (one or more) to the set. 40 | func (set *Set[T]) Add(items ...T) { 41 | for _, item := range items { 42 | set.items[item] = itemExists 43 | } 44 | } 45 | 46 | // Remove removes the items (one or more) from the set. 47 | func (set *Set[T]) Remove(items ...T) { 48 | for _, item := range items { 49 | delete(set.items, item) 50 | } 51 | } 52 | 53 | // Contains check if items (one or more) are present in the set. 54 | // All items have to be present in the set for the method to return true. 55 | // Returns true if no arguments are passed at all, i.e. set is always superset of empty set. 56 | func (set *Set[T]) Contains(items ...T) bool { 57 | for _, item := range items { 58 | if _, contains := set.items[item]; !contains { 59 | return false 60 | } 61 | } 62 | return true 63 | } 64 | 65 | // Empty returns true if set does not contain any elements. 66 | func (set *Set[T]) Empty() bool { 67 | return set.Size() == 0 68 | } 69 | 70 | // Size returns number of elements within the set. 71 | func (set *Set[T]) Size() int { 72 | return len(set.items) 73 | } 74 | 75 | // Clear clears all values in the set. 76 | func (set *Set[T]) Clear() { 77 | set.items = make(map[T]struct{}) 78 | } 79 | 80 | // Values returns all items in the set. 81 | func (set *Set[T]) Values() []T { 82 | values := make([]T, set.Size()) 83 | count := 0 84 | for item := range set.items { 85 | values[count] = item 86 | count++ 87 | } 88 | return values 89 | } 90 | 91 | // String returns a string representation of container 92 | func (set *Set[T]) String() string { 93 | str := "HashSet\n" 94 | items := []string{} 95 | for k := range set.items { 96 | items = append(items, fmt.Sprintf("%v", k)) 97 | } 98 | str += strings.Join(items, ", ") 99 | return str 100 | } 101 | -------------------------------------------------------------------------------- /sets/hashset/hashset_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hashset 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func TestSetNew(t *testing.T) { 12 | set := New[int](2, 1) 13 | 14 | if actualValue := set.Size(); actualValue != 2 { 15 | t.Errorf("Got %v expected %v", actualValue, 2) 16 | } 17 | if actualValue := set.Contains(1); actualValue != true { 18 | t.Errorf("Got %v expected %v", actualValue, true) 19 | } 20 | if actualValue := set.Contains(2); actualValue != true { 21 | t.Errorf("Got %v expected %v", actualValue, true) 22 | } 23 | if actualValue := set.Contains(3); actualValue != false { 24 | t.Errorf("Got %v expected %v", actualValue, true) 25 | } 26 | } 27 | 28 | func TestSetAdd(t *testing.T) { 29 | set := New[int]() 30 | set.Add() 31 | set.Add(1) 32 | set.Add(2) 33 | set.Add(2, 3) 34 | set.Add() 35 | if actualValue := set.Empty(); actualValue != false { 36 | t.Errorf("Got %v expected %v", actualValue, false) 37 | } 38 | if actualValue := set.Size(); actualValue != 3 { 39 | t.Errorf("Got %v expected %v", actualValue, 3) 40 | } 41 | } 42 | 43 | func TestSetContains(t *testing.T) { 44 | set := New[int]() 45 | set.Add(3, 1, 2) 46 | set.Add(2, 3) 47 | set.Add() 48 | if actualValue := set.Contains(); actualValue != true { 49 | t.Errorf("Got %v expected %v", actualValue, true) 50 | } 51 | if actualValue := set.Contains(1); actualValue != true { 52 | t.Errorf("Got %v expected %v", actualValue, true) 53 | } 54 | if actualValue := set.Contains(1, 2, 3); actualValue != true { 55 | t.Errorf("Got %v expected %v", actualValue, true) 56 | } 57 | if actualValue := set.Contains(1, 2, 3, 4); actualValue != false { 58 | t.Errorf("Got %v expected %v", actualValue, false) 59 | } 60 | } 61 | 62 | func TestSetRemove(t *testing.T) { 63 | set := New[int]() 64 | set.Add(3, 1, 2) 65 | set.Remove() 66 | if actualValue := set.Size(); actualValue != 3 { 67 | t.Errorf("Got %v expected %v", actualValue, 3) 68 | } 69 | set.Remove(1) 70 | if actualValue := set.Size(); actualValue != 2 { 71 | t.Errorf("Got %v expected %v", actualValue, 2) 72 | } 73 | set.Remove(3) 74 | set.Remove(3) 75 | set.Remove() 76 | set.Remove(2) 77 | if actualValue := set.Size(); actualValue != 0 { 78 | t.Errorf("Got %v expected %v", actualValue, 0) 79 | } 80 | } 81 | 82 | func TestSetSerialization(t *testing.T) { 83 | set := New[string]() 84 | set.Add("a", "b", "c") 85 | 86 | var err error 87 | assert := func() { 88 | if actualValue, expectedValue := set.Size(), 3; actualValue != expectedValue { 89 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 90 | } 91 | if actualValue := set.Contains("a", "b", "c"); actualValue != true { 92 | t.Errorf("Got %v expected %v", actualValue, true) 93 | } 94 | if err != nil { 95 | t.Errorf("Got error %v", err) 96 | } 97 | } 98 | 99 | assert() 100 | 101 | json, err := set.ToJSON() 102 | assert() 103 | 104 | err = set.FromJSON(json) 105 | assert() 106 | } 107 | 108 | func benchmarkContains(b *testing.B, set *Set[int], size int) { 109 | for i := 0; i < b.N; i++ { 110 | for n := 0; n < size; n++ { 111 | set.Contains(n) 112 | } 113 | } 114 | } 115 | 116 | func benchmarkAdd(b *testing.B, set *Set[int], size int) { 117 | for i := 0; i < b.N; i++ { 118 | for n := 0; n < size; n++ { 119 | set.Add(n) 120 | } 121 | } 122 | } 123 | 124 | func benchmarkRemove(b *testing.B, set *Set[int], size int) { 125 | for i := 0; i < b.N; i++ { 126 | for n := 0; n < size; n++ { 127 | set.Remove(n) 128 | } 129 | } 130 | } 131 | 132 | func BenchmarkHashSetContains100(b *testing.B) { 133 | b.StopTimer() 134 | size := 100 135 | set := New[int]() 136 | for n := 0; n < size; n++ { 137 | set.Add(n) 138 | } 139 | b.StartTimer() 140 | benchmarkContains(b, set, size) 141 | } 142 | 143 | func BenchmarkHashSetContains1000(b *testing.B) { 144 | b.StopTimer() 145 | size := 1000 146 | set := New[int]() 147 | for n := 0; n < size; n++ { 148 | set.Add(n) 149 | } 150 | b.StartTimer() 151 | benchmarkContains(b, set, size) 152 | } 153 | 154 | func BenchmarkHashSetContains10000(b *testing.B) { 155 | b.StopTimer() 156 | size := 10000 157 | set := New[int]() 158 | for n := 0; n < size; n++ { 159 | set.Add(n) 160 | } 161 | b.StartTimer() 162 | benchmarkContains(b, set, size) 163 | } 164 | 165 | func BenchmarkHashSetContains100000(b *testing.B) { 166 | b.StopTimer() 167 | size := 100000 168 | set := New[int]() 169 | for n := 0; n < size; n++ { 170 | set.Add(n) 171 | } 172 | b.StartTimer() 173 | benchmarkContains(b, set, size) 174 | } 175 | 176 | func BenchmarkHashSetAdd100(b *testing.B) { 177 | b.StopTimer() 178 | size := 100 179 | set := New[int]() 180 | b.StartTimer() 181 | benchmarkAdd(b, set, size) 182 | } 183 | 184 | func BenchmarkHashSetAdd1000(b *testing.B) { 185 | b.StopTimer() 186 | size := 1000 187 | set := New[int]() 188 | for n := 0; n < size; n++ { 189 | set.Add(n) 190 | } 191 | b.StartTimer() 192 | benchmarkAdd(b, set, size) 193 | } 194 | 195 | func BenchmarkHashSetAdd10000(b *testing.B) { 196 | b.StopTimer() 197 | size := 10000 198 | set := New[int]() 199 | for n := 0; n < size; n++ { 200 | set.Add(n) 201 | } 202 | b.StartTimer() 203 | benchmarkAdd(b, set, size) 204 | } 205 | 206 | func BenchmarkHashSetAdd100000(b *testing.B) { 207 | b.StopTimer() 208 | size := 100000 209 | set := New[int]() 210 | for n := 0; n < size; n++ { 211 | set.Add(n) 212 | } 213 | b.StartTimer() 214 | benchmarkAdd(b, set, size) 215 | } 216 | 217 | func BenchmarkHashSetRemove100(b *testing.B) { 218 | b.StopTimer() 219 | size := 100 220 | set := New[int]() 221 | for n := 0; n < size; n++ { 222 | set.Add(n) 223 | } 224 | b.StartTimer() 225 | benchmarkRemove(b, set, size) 226 | } 227 | 228 | func BenchmarkHashSetRemove1000(b *testing.B) { 229 | b.StopTimer() 230 | size := 1000 231 | set := New[int]() 232 | for n := 0; n < size; n++ { 233 | set.Add(n) 234 | } 235 | b.StartTimer() 236 | benchmarkRemove(b, set, size) 237 | } 238 | 239 | func BenchmarkHashSetRemove10000(b *testing.B) { 240 | b.StopTimer() 241 | size := 10000 242 | set := New[int]() 243 | for n := 0; n < size; n++ { 244 | set.Add(n) 245 | } 246 | b.StartTimer() 247 | benchmarkRemove(b, set, size) 248 | } 249 | 250 | func BenchmarkHashSetRemove100000(b *testing.B) { 251 | b.StopTimer() 252 | size := 100000 253 | set := New[int]() 254 | for n := 0; n < size; n++ { 255 | set.Add(n) 256 | } 257 | b.StartTimer() 258 | benchmarkRemove(b, set, size) 259 | } 260 | -------------------------------------------------------------------------------- /sets/hashset/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hashset 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | ) 12 | 13 | func assertSerializationImplementation() { 14 | var _ containers.JSONSerializer = (*Set[string])(nil) 15 | var _ containers.JSONDeserializer = (*Set[string])(nil) 16 | } 17 | 18 | // ToJSON outputs the JSON representation of the set. 19 | func (set *Set[T]) ToJSON() ([]byte, error) { 20 | return json.Marshal(set.Values()) 21 | } 22 | 23 | // FromJSON populates the set from the input JSON representation. 24 | func (set *Set[T]) FromJSON(data []byte) error { 25 | elements := []T{} 26 | err := json.Unmarshal(data, &elements) 27 | if err == nil { 28 | set.Clear() 29 | set.Add(elements...) 30 | } 31 | return err 32 | } 33 | -------------------------------------------------------------------------------- /sets/linkedhashset/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package linkedhashset 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertEnumerableImplementation() { 10 | var _ containers.EnumerableWithIndex[string] = (*Set[string])(nil) 11 | } 12 | 13 | // Each calls the given function once for each element, passing that element's index and value. 14 | func (set *Set[T]) Each(f func(index int, value T)) { 15 | iterator := set.Iterator() 16 | for iterator.Next() { 17 | f(iterator.Index(), iterator.Value()) 18 | } 19 | } 20 | 21 | // Map invokes the given function once for each element and returns a 22 | // container containing the values returned by the given function. 23 | func (set *Set[T]) Map(f func(index int, value T) T) *Set[T] { 24 | newSet := New[T]() 25 | iterator := set.Iterator() 26 | for iterator.Next() { 27 | newSet.Add(f(iterator.Index(), iterator.Value())) 28 | } 29 | return newSet 30 | } 31 | 32 | // Select returns a new container containing all elements for which the given function returns a true value. 33 | func (set *Set[T]) Select(f func(index int, value T) bool) *Set[T] { 34 | newSet := New[T]() 35 | iterator := set.Iterator() 36 | for iterator.Next() { 37 | if f(iterator.Index(), iterator.Value()) { 38 | newSet.Add(iterator.Value()) 39 | } 40 | } 41 | return newSet 42 | } 43 | 44 | // Any passes each element of the container to the given function and 45 | // returns true if the function ever returns true for any element. 46 | func (set *Set[T]) Any(f func(index int, value T) bool) bool { 47 | iterator := set.Iterator() 48 | for iterator.Next() { 49 | if f(iterator.Index(), iterator.Value()) { 50 | return true 51 | } 52 | } 53 | return false 54 | } 55 | 56 | // All passes each element of the container to the given function and 57 | // returns true if the function returns true for all elements. 58 | func (set *Set[T]) All(f func(index int, value T) bool) bool { 59 | iterator := set.Iterator() 60 | for iterator.Next() { 61 | if !f(iterator.Index(), iterator.Value()) { 62 | return false 63 | } 64 | } 65 | return true 66 | } 67 | 68 | // Find passes each element of the container to the given function and returns 69 | // the first (index,value) for which the function is true or -1,nil otherwise 70 | // if no element matches the criteria. 71 | func (set *Set[T]) Find(f func(index int, value T) bool) (int, T) { 72 | iterator := set.Iterator() 73 | for iterator.Next() { 74 | if f(iterator.Index(), iterator.Value()) { 75 | return iterator.Index(), iterator.Value() 76 | } 77 | } 78 | return -1, *new(T) 79 | } 80 | -------------------------------------------------------------------------------- /sets/linkedhashset/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package linkedhashset 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/containers" 9 | "github.com/daichi-m/go18ds/lists/doublylinkedlist" 10 | ) 11 | 12 | func assertIteratorImplementation() { 13 | var _ containers.ReverseIteratorWithIndex[string] = (*Iterator[string])(nil) 14 | } 15 | 16 | // Iterator holding the iterator's state 17 | type Iterator[T comparable] struct { 18 | iterator doublylinkedlist.Iterator[T] 19 | } 20 | 21 | // Iterator returns a stateful iterator whose values can be fetched by an index. 22 | func (set *Set[T]) Iterator() Iterator[T] { 23 | return Iterator[T]{iterator: set.ordering.Iterator()} 24 | } 25 | 26 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 27 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 28 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 29 | // Modifies the state of the iterator. 30 | func (iterator *Iterator[T]) Next() bool { 31 | return iterator.iterator.Next() 32 | } 33 | 34 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 35 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 36 | // Modifies the state of the iterator. 37 | func (iterator *Iterator[T]) Prev() bool { 38 | return iterator.iterator.Prev() 39 | } 40 | 41 | // Value returns the current element's value. 42 | // Does not modify the state of the iterator. 43 | func (iterator *Iterator[T]) Value() T { 44 | return iterator.iterator.Value() 45 | } 46 | 47 | // Index returns the current element's index. 48 | // Does not modify the state of the iterator. 49 | func (iterator *Iterator[T]) Index() int { 50 | return iterator.iterator.Index() 51 | } 52 | 53 | // Begin resets the iterator to its initial state (one-before-first) 54 | // Call Next() to fetch the first element if any. 55 | func (iterator *Iterator[T]) Begin() { 56 | iterator.iterator.Begin() 57 | } 58 | 59 | // End moves the iterator past the last element (one-past-the-end). 60 | // Call Prev() to fetch the last element if any. 61 | func (iterator *Iterator[T]) End() { 62 | iterator.iterator.End() 63 | } 64 | 65 | // First moves the iterator to the first element and returns true if there was a first element in the container. 66 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 67 | // Modifies the state of the iterator. 68 | func (iterator *Iterator[T]) First() bool { 69 | return iterator.iterator.First() 70 | } 71 | 72 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 73 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 74 | // Modifies the state of the iterator. 75 | func (iterator *Iterator[T]) Last() bool { 76 | return iterator.iterator.Last() 77 | } 78 | -------------------------------------------------------------------------------- /sets/linkedhashset/linkedhashset.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package linkedhashset is a set that preserves insertion-order. 6 | // 7 | // It is backed by a hash table to store values and doubly-linked list to store ordering. 8 | // 9 | // Note that insertion-order is not affected if an element is re-inserted into the set. 10 | // 11 | // Structure is not thread safe. 12 | // 13 | // References: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29 14 | package linkedhashset 15 | 16 | import ( 17 | "fmt" 18 | "strings" 19 | 20 | "github.com/daichi-m/go18ds/lists/doublylinkedlist" 21 | "github.com/daichi-m/go18ds/sets" 22 | ) 23 | 24 | func assertSetImplementation() { 25 | var _ sets.Set[string] = (*Set[string])(nil) 26 | } 27 | 28 | // Set holds elements in go's native map 29 | type Set[T comparable] struct { 30 | table map[T]struct{} 31 | ordering *doublylinkedlist.List[T] 32 | } 33 | 34 | var itemExists = struct{}{} 35 | 36 | // New instantiates a new empty set and adds the passed values, if any, to the set 37 | func New[T comparable](values ...T) *Set[T] { 38 | set := &Set[T]{ 39 | table: make(map[T]struct{}), 40 | ordering: doublylinkedlist.New[T](), 41 | } 42 | if len(values) > 0 { 43 | set.Add(values...) 44 | } 45 | return set 46 | } 47 | 48 | // Add adds the items (one or more) to the set. 49 | // Note that insertion-order is not affected if an element is re-inserted into the set. 50 | func (set *Set[T]) Add(items ...T) { 51 | for _, item := range items { 52 | if _, contains := set.table[item]; !contains { 53 | set.table[item] = itemExists 54 | set.ordering.Append(item) 55 | } 56 | } 57 | } 58 | 59 | // Remove removes the items (one or more) from the set. 60 | // Slow operation, worst-case O(n^2). 61 | func (set *Set[T]) Remove(items ...T) { 62 | for _, item := range items { 63 | if _, contains := set.table[item]; contains { 64 | delete(set.table, item) 65 | index := set.ordering.IndexOf(item) 66 | set.ordering.Remove(index) 67 | } 68 | } 69 | } 70 | 71 | // Contains check if items (one or more) are present in the set. 72 | // All items have to be present in the set for the method to return true. 73 | // Returns true if no arguments are passed at all, i.e. set is always superset of empty set. 74 | func (set *Set[T]) Contains(items ...T) bool { 75 | for _, item := range items { 76 | if _, contains := set.table[item]; !contains { 77 | return false 78 | } 79 | } 80 | return true 81 | } 82 | 83 | // Empty returns true if set does not contain any elements. 84 | func (set *Set[T]) Empty() bool { 85 | return set.Size() == 0 86 | } 87 | 88 | // Size returns number of elements within the set. 89 | func (set *Set[T]) Size() int { 90 | return set.ordering.Size() 91 | } 92 | 93 | // Clear clears all values in the set. 94 | func (set *Set[T]) Clear() { 95 | set.table = make(map[T]struct{}) 96 | set.ordering.Clear() 97 | } 98 | 99 | // Values returns all items in the set. 100 | func (set *Set[T]) Values() []T { 101 | values := make([]T, set.Size()) 102 | it := set.Iterator() 103 | for it.Next() { 104 | values[it.Index()] = it.Value() 105 | } 106 | return values 107 | } 108 | 109 | // String returns a string representation of container 110 | func (set *Set[T]) String() string { 111 | str := "LinkedHashSet\n" 112 | items := []string{} 113 | it := set.Iterator() 114 | for it.Next() { 115 | items = append(items, fmt.Sprintf("%v", it.Value())) 116 | } 117 | str += strings.Join(items, ", ") 118 | return str 119 | } 120 | -------------------------------------------------------------------------------- /sets/linkedhashset/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package linkedhashset 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | ) 12 | 13 | func assertSerializationImplementation() { 14 | var _ containers.JSONSerializer = (*Set[string])(nil) 15 | var _ containers.JSONDeserializer = (*Set[string])(nil) 16 | } 17 | 18 | // ToJSON outputs the JSON representation of the set. 19 | func (set *Set[T]) ToJSON() ([]byte, error) { 20 | return json.Marshal(set.Values()) 21 | } 22 | 23 | // FromJSON populates the set from the input JSON representation. 24 | func (set *Set[T]) FromJSON(data []byte) error { 25 | elements := []T{} 26 | err := json.Unmarshal(data, &elements) 27 | if err == nil { 28 | set.Clear() 29 | set.Add(elements...) 30 | } 31 | return err 32 | } 33 | -------------------------------------------------------------------------------- /sets/sets.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package sets provides an abstract Set interface. 6 | // 7 | // In computer science, a set is an abstract data type that can store certain values and no repeated values. It is a computer implementation of the mathematical concept of a finite set. Unlike most other collection types, rather than retrieving a specific element from a set, one typically tests a value for membership in a set. 8 | // 9 | // Reference: https://en.wikipedia.org/wiki/Set_%28abstract_data_type%29 10 | package sets 11 | 12 | import "github.com/daichi-m/go18ds/containers" 13 | 14 | // Set interface that all sets implement 15 | type Set[T comparable] interface { 16 | Add(elements ...T) 17 | Remove(elements ...T) 18 | Contains(elements ...T) bool 19 | 20 | containers.Container[T] 21 | // Empty() bool 22 | // Size() int 23 | // Clear() 24 | // Values() []T 25 | } 26 | -------------------------------------------------------------------------------- /sets/treeset/enumerable.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treeset 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/containers" 9 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 10 | ) 11 | 12 | func assertEnumerableImplementation() { 13 | var _ containers.EnumerableWithIndex[string] = (*Set[string])(nil) 14 | } 15 | 16 | // Each calls the given function once for each element, passing that element's index and value. 17 | func (set *Set[T]) Each(f func(index int, value T)) { 18 | iterator := set.Iterator() 19 | for iterator.Next() { 20 | f(iterator.Index(), iterator.Value()) 21 | } 22 | } 23 | 24 | // Map invokes the given function once for each element and returns a 25 | // container containing the values returned by the given function. 26 | func (set *Set[T]) Map(f func(index int, value T) T) *Set[T] { 27 | newSet := &Set[T]{tree: rbt.NewWith[T, presence](set.tree.Comparator)} 28 | iterator := set.Iterator() 29 | for iterator.Next() { 30 | newSet.Add(f(iterator.Index(), iterator.Value())) 31 | } 32 | return newSet 33 | } 34 | 35 | // Select returns a new container containing all elements for which the given function returns a true value. 36 | func (set *Set[T]) Select(f func(index int, value T) bool) *Set[T] { 37 | newSet := &Set[T]{tree: rbt.NewWith[T, presence](set.tree.Comparator)} 38 | iterator := set.Iterator() 39 | for iterator.Next() { 40 | if f(iterator.Index(), iterator.Value()) { 41 | newSet.Add(iterator.Value()) 42 | } 43 | } 44 | return newSet 45 | } 46 | 47 | // Any passes each element of the container to the given function and 48 | // returns true if the function ever returns true for any element. 49 | func (set *Set[T]) Any(f func(index int, value T) bool) bool { 50 | iterator := set.Iterator() 51 | for iterator.Next() { 52 | if f(iterator.Index(), iterator.Value()) { 53 | return true 54 | } 55 | } 56 | return false 57 | } 58 | 59 | // All passes each element of the container to the given function and 60 | // returns true if the function returns true for all elements. 61 | func (set *Set[T]) All(f func(index int, value T) bool) bool { 62 | iterator := set.Iterator() 63 | for iterator.Next() { 64 | if !f(iterator.Index(), iterator.Value()) { 65 | return false 66 | } 67 | } 68 | return true 69 | } 70 | 71 | // Find passes each element of the container to the given function and returns 72 | // the first (index,value) for which the function is true or -1,nil otherwise 73 | // if no element matches the criteria. 74 | func (set *Set[T]) Find(f func(index int, value T) bool) (int, T) { 75 | iterator := set.Iterator() 76 | for iterator.Next() { 77 | if f(iterator.Index(), iterator.Value()) { 78 | return iterator.Index(), iterator.Value() 79 | } 80 | } 81 | return -1, *new(T) 82 | } 83 | -------------------------------------------------------------------------------- /sets/treeset/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treeset 6 | 7 | import ( 8 | "github.com/daichi-m/go18ds/containers" 9 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 10 | ) 11 | 12 | func assertIteratorImplementation() { 13 | var _ containers.ReverseIteratorWithIndex[string] = (*Iterator[string])(nil) 14 | } 15 | 16 | // Iterator returns a stateful iterator whose values can be fetched by an index. 17 | type Iterator[T comparable] struct { 18 | index int 19 | iterator rbt.Iterator[T, presence] 20 | tree *rbt.Tree[T, presence] 21 | } 22 | 23 | // Iterator holding the iterator's state 24 | func (set *Set[T]) Iterator() Iterator[T] { 25 | return Iterator[T]{index: -1, iterator: set.tree.Iterator(), tree: set.tree} 26 | } 27 | 28 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 29 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 30 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 31 | // Modifies the state of the iterator. 32 | func (iterator *Iterator[T]) Next() bool { 33 | if iterator.index < iterator.tree.Size() { 34 | iterator.index++ 35 | } 36 | return iterator.iterator.Next() 37 | } 38 | 39 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 40 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 41 | // Modifies the state of the iterator. 42 | func (iterator *Iterator[T]) Prev() bool { 43 | if iterator.index >= 0 { 44 | iterator.index-- 45 | } 46 | return iterator.iterator.Prev() 47 | } 48 | 49 | // Value returns the current element's value. 50 | // Does not modify the state of the iterator. 51 | func (iterator *Iterator[T]) Value() T { 52 | return iterator.iterator.Key() 53 | } 54 | 55 | // Index returns the current element's index. 56 | // Does not modify the state of the iterator. 57 | func (iterator *Iterator[T]) Index() int { 58 | return iterator.index 59 | } 60 | 61 | // Begin resets the iterator to its initial state (one-before-first) 62 | // Call Next() to fetch the first element if any. 63 | func (iterator *Iterator[T]) Begin() { 64 | iterator.index = -1 65 | iterator.iterator.Begin() 66 | } 67 | 68 | // End moves the iterator past the last element (one-past-the-end). 69 | // Call Prev() to fetch the last element if any. 70 | func (iterator *Iterator[T]) End() { 71 | iterator.index = iterator.tree.Size() 72 | iterator.iterator.End() 73 | } 74 | 75 | // First moves the iterator to the first element and returns true if there was a first element in the container. 76 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 77 | // Modifies the state of the iterator. 78 | func (iterator *Iterator[T]) First() bool { 79 | iterator.Begin() 80 | return iterator.Next() 81 | } 82 | 83 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 84 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 85 | // Modifies the state of the iterator. 86 | func (iterator *Iterator[T]) Last() bool { 87 | iterator.End() 88 | return iterator.Prev() 89 | } 90 | -------------------------------------------------------------------------------- /sets/treeset/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package treeset 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | ) 12 | 13 | func assertSerializationImplementation() { 14 | var _ containers.JSONSerializer = (*Set[string])(nil) 15 | var _ containers.JSONDeserializer = (*Set[string])(nil) 16 | } 17 | 18 | // ToJSON outputs the JSON representation of the set. 19 | func (set *Set[T]) ToJSON() ([]byte, error) { 20 | return json.Marshal(set.Values()) 21 | } 22 | 23 | // FromJSON populates the set from the input JSON representation. 24 | func (set *Set[T]) FromJSON(data []byte) error { 25 | elements := []T{} 26 | err := json.Unmarshal(data, &elements) 27 | if err == nil { 28 | set.Clear() 29 | set.Add(elements...) 30 | } 31 | return err 32 | } 33 | -------------------------------------------------------------------------------- /sets/treeset/treeset.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package treeset implements a tree backed by a red-black tree. 6 | // 7 | // Structure is not thread safe. 8 | // 9 | // Reference: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29 10 | package treeset 11 | 12 | import ( 13 | "fmt" 14 | "strings" 15 | 16 | "github.com/daichi-m/go18ds/sets" 17 | rbt "github.com/daichi-m/go18ds/trees/redblacktree" 18 | "github.com/daichi-m/go18ds/utils" 19 | ) 20 | 21 | func assertSetImplementation() { 22 | var _ sets.Set[string] = (*Set[string])(nil) 23 | } 24 | 25 | type presence struct{} 26 | 27 | var present presence 28 | 29 | // Set holds elements in a red-black tree 30 | type Set[T comparable] struct { 31 | tree *rbt.Tree[T, presence] 32 | } 33 | 34 | // NewWith instantiates a new empty set with the custom comparator. 35 | func NewWith[T comparable](comparator utils.Comparator[T], values ...T) *Set[T] { 36 | set := &Set[T]{tree: rbt.NewWith[T, presence](comparator)} 37 | if len(values) > 0 { 38 | set.Add(values...) 39 | } 40 | return set 41 | } 42 | 43 | // NewWithIntComparator instantiates a new empty set with the IntComparator, i.e. keys are of type int. 44 | func NewWithIntComparator(values ...int) *Set[int] { 45 | set := &Set[int]{tree: rbt.NewWithIntComparator[presence]()} 46 | if len(values) > 0 { 47 | set.Add(values...) 48 | } 49 | return set 50 | } 51 | 52 | // NewWithStringComparator instantiates a new empty set with the StringComparator, i.e. keys are of type string. 53 | func NewWithStringComparator(values ...string) *Set[string] { 54 | set := &Set[string]{tree: rbt.NewWithStringComparator[presence]()} 55 | if len(values) > 0 { 56 | set.Add(values...) 57 | } 58 | return set 59 | } 60 | 61 | // Add adds the items (one or more) to the set. 62 | func (set *Set[T]) Add(items ...T) { 63 | for _, item := range items { 64 | set.tree.Put(item, present) 65 | } 66 | } 67 | 68 | // Remove removes the items (one or more) from the set. 69 | func (set *Set[T]) Remove(items ...T) { 70 | for _, item := range items { 71 | set.tree.Remove(item) 72 | } 73 | } 74 | 75 | // Contains checks weather items (one or more) are present in the set. 76 | // All items have to be present in the set for the method to return true. 77 | // Returns true if no arguments are passed at all, i.e. set is always superset of empty set. 78 | func (set *Set[T]) Contains(items ...T) bool { 79 | for _, item := range items { 80 | if _, contains := set.tree.Get(item); !contains { 81 | return false 82 | } 83 | } 84 | return true 85 | } 86 | 87 | // Empty returns true if set does not contain any elements. 88 | func (set *Set[T]) Empty() bool { 89 | return set.tree.Size() == 0 90 | } 91 | 92 | // Size returns number of elements within the set. 93 | func (set *Set[T]) Size() int { 94 | return set.tree.Size() 95 | } 96 | 97 | // Clear clears all values in the set. 98 | func (set *Set[T]) Clear() { 99 | set.tree.Clear() 100 | } 101 | 102 | // Values returns all items in the set. 103 | func (set *Set[T]) Values() []T { 104 | return set.tree.Keys() 105 | } 106 | 107 | // String returns a string representation of container 108 | func (set *Set[T]) String() string { 109 | str := "TreeSet\n" 110 | items := []string{} 111 | for _, v := range set.tree.Keys() { 112 | items = append(items, fmt.Sprintf("%v", v)) 113 | } 114 | str += strings.Join(items, ", ") 115 | return str 116 | } 117 | -------------------------------------------------------------------------------- /stacks/arraystack/arraystack.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package arraystack implements a stack backed by array list. 6 | // 7 | // Structure is not thread safe. 8 | // 9 | // Reference: https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29#Array 10 | package arraystack 11 | 12 | import ( 13 | "fmt" 14 | "strings" 15 | 16 | "github.com/daichi-m/go18ds/lists/arraylist" 17 | "github.com/daichi-m/go18ds/stacks" 18 | ) 19 | 20 | func assertStackImplementation() { 21 | var _ stacks.Stack[string] = (*Stack[string])(nil) 22 | } 23 | 24 | // Stack holds elements in an array-list 25 | type Stack[T comparable] struct { 26 | list *arraylist.List[T] 27 | } 28 | 29 | // New instantiates a new empty stack 30 | func New[T comparable]() *Stack[T] { 31 | return &Stack[T]{list: arraylist.New[T]()} 32 | } 33 | 34 | // Push adds a value onto the top of the stack 35 | func (stack *Stack[T]) Push(value T) { 36 | stack.list.Add(value) 37 | } 38 | 39 | // Pop removes top element on stack and returns it, or nil if stack is empty. 40 | // Second return parameter is true, unless the stack was empty and there was nothing to pop. 41 | func (stack *Stack[T]) Pop() (value T, ok bool) { 42 | value, ok = stack.list.Get(stack.list.Size() - 1) 43 | stack.list.Remove(stack.list.Size() - 1) 44 | return 45 | } 46 | 47 | // Peek returns top element on the stack without removing it, or nil if stack is empty. 48 | // Second return parameter is true, unless the stack was empty and there was nothing to peek. 49 | func (stack *Stack[T]) Peek() (value T, ok bool) { 50 | return stack.list.Get(stack.list.Size() - 1) 51 | } 52 | 53 | // Empty returns true if stack does not contain any elements. 54 | func (stack *Stack[T]) Empty() bool { 55 | return stack.list.Empty() 56 | } 57 | 58 | // Size returns number of elements within the stack. 59 | func (stack *Stack[T]) Size() int { 60 | return stack.list.Size() 61 | } 62 | 63 | // Clear removes all elements from the stack. 64 | func (stack *Stack[T]) Clear() { 65 | stack.list.Clear() 66 | } 67 | 68 | // Values returns all elements in the stack (LIFO order). 69 | func (stack *Stack[T]) Values() []T { 70 | size := stack.list.Size() 71 | elements := make([]T, size, size) 72 | for i := 1; i <= size; i++ { 73 | elements[size-i], _ = stack.list.Get(i - 1) // in reverse (LIFO) 74 | } 75 | return elements 76 | } 77 | 78 | // String returns a string representation of container 79 | func (stack *Stack[T]) String() string { 80 | str := "ArrayStack\n" 81 | values := []string{} 82 | for _, value := range stack.list.Values() { 83 | values = append(values, fmt.Sprintf("%v", value)) 84 | } 85 | str += strings.Join(values, ", ") 86 | return str 87 | } 88 | 89 | // Check that the index is within bounds of the list 90 | func (stack *Stack[T]) withinRange(index int) bool { 91 | return index >= 0 && index < stack.list.Size() 92 | } 93 | -------------------------------------------------------------------------------- /stacks/arraystack/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arraystack 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.ReverseIteratorWithIndex[string] = (*Iterator[string])(nil) 11 | } 12 | 13 | // Iterator returns a stateful iterator whose values can be fetched by an index. 14 | type Iterator[T comparable] struct { 15 | stack *Stack[T] 16 | index int 17 | } 18 | 19 | // Iterator returns a stateful iterator whose values can be fetched by an index. 20 | func (stack *Stack[T]) Iterator() Iterator[T] { 21 | return Iterator[T]{stack: stack, index: -1} 22 | } 23 | 24 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 25 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 26 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 27 | // Modifies the state of the iterator. 28 | func (iterator *Iterator[T]) Next() bool { 29 | if iterator.index < iterator.stack.Size() { 30 | iterator.index++ 31 | } 32 | return iterator.stack.withinRange(iterator.index) 33 | } 34 | 35 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 36 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 37 | // Modifies the state of the iterator. 38 | func (iterator *Iterator[T]) Prev() bool { 39 | if iterator.index >= 0 { 40 | iterator.index-- 41 | } 42 | return iterator.stack.withinRange(iterator.index) 43 | } 44 | 45 | // Value returns the current element's value. 46 | // Does not modify the state of the iterator. 47 | func (iterator *Iterator[T]) Value() T { 48 | value, _ := iterator.stack.list.Get(iterator.stack.list.Size() - iterator.index - 1) // in reverse (LIFO) 49 | return value 50 | } 51 | 52 | // Index returns the current element's index. 53 | // Does not modify the state of the iterator. 54 | func (iterator *Iterator[T]) Index() int { 55 | return iterator.index 56 | } 57 | 58 | // Begin resets the iterator to its initial state (one-before-first) 59 | // Call Next() to fetch the first element if any. 60 | func (iterator *Iterator[T]) Begin() { 61 | iterator.index = -1 62 | } 63 | 64 | // End moves the iterator past the last element (one-past-the-end). 65 | // Call Prev() to fetch the last element if any. 66 | func (iterator *Iterator[T]) End() { 67 | iterator.index = iterator.stack.Size() 68 | } 69 | 70 | // First moves the iterator to the first element and returns true if there was a first element in the container. 71 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 72 | // Modifies the state of the iterator. 73 | func (iterator *Iterator[T]) First() bool { 74 | iterator.Begin() 75 | return iterator.Next() 76 | } 77 | 78 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 79 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 80 | // Modifies the state of the iterator. 81 | func (iterator *Iterator[T]) Last() bool { 82 | iterator.End() 83 | return iterator.Prev() 84 | } 85 | -------------------------------------------------------------------------------- /stacks/arraystack/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arraystack 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertSerializationImplementation() { 10 | var _ containers.JSONSerializer = (*Stack[string])(nil) 11 | var _ containers.JSONDeserializer = (*Stack[string])(nil) 12 | } 13 | 14 | // ToJSON outputs the JSON representation of the stack. 15 | func (stack *Stack[T]) ToJSON() ([]byte, error) { 16 | return stack.list.ToJSON() 17 | } 18 | 19 | // FromJSON populates the stack from the input JSON representation. 20 | func (stack *Stack[T]) FromJSON(data []byte) error { 21 | return stack.list.FromJSON(data) 22 | } 23 | -------------------------------------------------------------------------------- /stacks/linkedliststack/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package linkedliststack 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.IteratorWithIndex[string] = (*Iterator[string])(nil) 11 | } 12 | 13 | // Iterator returns a stateful iterator whose values can be fetched by an index. 14 | type Iterator[T comparable] struct { 15 | stack *Stack[T] 16 | index int 17 | } 18 | 19 | // Iterator returns a stateful iterator whose values can be fetched by an index. 20 | func (stack *Stack[T]) Iterator() Iterator[T] { 21 | return Iterator[T]{stack: stack, index: -1} 22 | } 23 | 24 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 25 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 26 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 27 | // Modifies the state of the iterator. 28 | func (iterator *Iterator[T]) Next() bool { 29 | if iterator.index < iterator.stack.Size() { 30 | iterator.index++ 31 | } 32 | return iterator.stack.withinRange(iterator.index) 33 | } 34 | 35 | // Value returns the current element's value. 36 | // Does not modify the state of the iterator. 37 | func (iterator *Iterator[T]) Value() T { 38 | value, _ := iterator.stack.list.Get(iterator.index) // in reverse (LIFO) 39 | return value 40 | } 41 | 42 | // Index returns the current element's index. 43 | // Does not modify the state of the iterator. 44 | func (iterator *Iterator[T]) Index() int { 45 | return iterator.index 46 | } 47 | 48 | // Begin resets the iterator to its initial state (one-before-first) 49 | // Call Next() to fetch the first element if any. 50 | func (iterator *Iterator[T]) Begin() { 51 | iterator.index = -1 52 | } 53 | 54 | // First moves the iterator to the first element and returns true if there was a first element in the container. 55 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 56 | // Modifies the state of the iterator. 57 | func (iterator *Iterator[T]) First() bool { 58 | iterator.Begin() 59 | return iterator.Next() 60 | } 61 | -------------------------------------------------------------------------------- /stacks/linkedliststack/linkedliststack.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package linkedliststack implements a stack backed by a singly-linked list. 6 | // 7 | // Structure is not thread safe. 8 | // 9 | // Reference:https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29#Linked_list 10 | package linkedliststack 11 | 12 | import ( 13 | "fmt" 14 | "strings" 15 | 16 | "github.com/daichi-m/go18ds/lists/singlylinkedlist" 17 | "github.com/daichi-m/go18ds/stacks" 18 | ) 19 | 20 | func assertStackImplementation() { 21 | var _ stacks.Stack[string] = (*Stack[string])(nil) 22 | } 23 | 24 | // Stack holds elements in a singly-linked-list 25 | type Stack[T comparable] struct { 26 | list *singlylinkedlist.List[T] 27 | } 28 | 29 | // New nnstantiates a new empty stack 30 | func New[T comparable]() *Stack[T] { 31 | return &Stack[T]{list: &singlylinkedlist.List[T]{}} 32 | } 33 | 34 | // Push adds a value onto the top of the stack 35 | func (stack *Stack[T]) Push(value T) { 36 | stack.list.Prepend(value) 37 | } 38 | 39 | // Pop removes top element on stack and returns it, or nil if stack is empty. 40 | // Second return parameter is true, unless the stack was empty and there was nothing to pop. 41 | func (stack *Stack[T]) Pop() (value T, ok bool) { 42 | value, ok = stack.list.Get(0) 43 | stack.list.Remove(0) 44 | return 45 | } 46 | 47 | // Peek returns top element on the stack without removing it, or nil if stack is empty. 48 | // Second return parameter is true, unless the stack was empty and there was nothing to peek. 49 | func (stack *Stack[T]) Peek() (value T, ok bool) { 50 | return stack.list.Get(0) 51 | } 52 | 53 | // Empty returns true if stack does not contain any elements. 54 | func (stack *Stack[T]) Empty() bool { 55 | return stack.list.Empty() 56 | } 57 | 58 | // Size returns number of elements within the stack. 59 | func (stack *Stack[T]) Size() int { 60 | return stack.list.Size() 61 | } 62 | 63 | // Clear removes all elements from the stack. 64 | func (stack *Stack[T]) Clear() { 65 | stack.list.Clear() 66 | } 67 | 68 | // Values returns all elements in the stack (LIFO order). 69 | func (stack *Stack[T]) Values() []T { 70 | return stack.list.Values() 71 | } 72 | 73 | // String returns a string representation of container 74 | func (stack *Stack[T]) String() string { 75 | str := "LinkedListStack\n" 76 | values := []string{} 77 | for _, value := range stack.list.Values() { 78 | values = append(values, fmt.Sprintf("%v", value)) 79 | } 80 | str += strings.Join(values, ", ") 81 | return str 82 | } 83 | 84 | // Check that the index is within bounds of the list 85 | func (stack *Stack[T]) withinRange(index int) bool { 86 | return index >= 0 && index < stack.list.Size() 87 | } 88 | -------------------------------------------------------------------------------- /stacks/linkedliststack/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package linkedliststack 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertSerializationImplementation() { 10 | var _ containers.JSONSerializer = (*Stack[string])(nil) 11 | var _ containers.JSONDeserializer = (*Stack[string])(nil) 12 | } 13 | 14 | // ToJSON outputs the JSON representation of the stack. 15 | func (stack *Stack[T]) ToJSON() ([]byte, error) { 16 | return stack.list.ToJSON() 17 | } 18 | 19 | // FromJSON populates the stack from the input JSON representation. 20 | func (stack *Stack[T]) FromJSON(data []byte) error { 21 | return stack.list.FromJSON(data) 22 | } 23 | -------------------------------------------------------------------------------- /stacks/stacks.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package stacks provides an abstract Stack interface. 6 | // 7 | // In computer science, a stack is an abstract data type that serves as a collection of elements, with two principal operations: push, which adds an element to the collection, and pop, which removes the most recently added element that was not yet removed. The order in which elements come off a stack gives rise to its alternative name, LIFO (for last in, first out). Additionally, a peek operation may give access to the top without modifying the stack. 8 | // 9 | // Reference: https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29 10 | package stacks 11 | 12 | import "github.com/daichi-m/go18ds/containers" 13 | 14 | // Stack interface that all stacks implement 15 | type Stack[T comparable] interface { 16 | Push(value T) 17 | Pop() (value T, ok bool) 18 | Peek() (value T, ok bool) 19 | 20 | containers.Container[T] 21 | // Empty() bool 22 | // Size() int 23 | // Clear() 24 | // Values() []interface{} 25 | } 26 | -------------------------------------------------------------------------------- /trees/avltree/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, Benjamin Scher Purcell. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package avltree 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.ReverseIteratorWithKey[string, string] = (*Iterator[string, string])(nil) 11 | } 12 | 13 | // Iterator holding the iterator's state 14 | type Iterator[K comparable, V comparable] struct { 15 | tree *Tree[K, V] 16 | node *Node[K, V] 17 | position position 18 | } 19 | 20 | type position byte 21 | 22 | const ( 23 | begin, between, end position = 0, 1, 2 24 | ) 25 | 26 | // Iterator returns a stateful iterator whose elements are key/value pairs. 27 | func (tree *Tree[K, V]) Iterator() containers.ReverseIteratorWithKey[K, V] { 28 | return &Iterator[K, V]{tree: tree, node: nil, position: begin} 29 | } 30 | 31 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 32 | // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). 33 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 34 | // Modifies the state of the iterator. 35 | func (iterator *Iterator[K, V]) Next() bool { 36 | switch iterator.position { 37 | case begin: 38 | iterator.position = between 39 | iterator.node = iterator.tree.Left() 40 | case between: 41 | iterator.node = iterator.node.Next() 42 | } 43 | 44 | if iterator.node == nil { 45 | iterator.position = end 46 | return false 47 | } 48 | return true 49 | } 50 | 51 | // Prev moves the iterator to the next element and returns true if there was a previous element in the container. 52 | // If Prev() returns true, then next element's key and value can be retrieved by Key() and Value(). 53 | // If Prev() was called for the first time, then it will point the iterator to the first element if it exists. 54 | // Modifies the state of the iterator. 55 | func (iterator *Iterator[K, V]) Prev() bool { 56 | switch iterator.position { 57 | case end: 58 | iterator.position = between 59 | iterator.node = iterator.tree.Right() 60 | case between: 61 | iterator.node = iterator.node.Prev() 62 | } 63 | 64 | if iterator.node == nil { 65 | iterator.position = begin 66 | return false 67 | } 68 | return true 69 | } 70 | 71 | // Value returns the current element's value. 72 | // Does not modify the state of the iterator. 73 | func (iterator *Iterator[K, V]) Value() V { 74 | if iterator.node == nil { 75 | return *new(V) 76 | } 77 | return iterator.node.Value 78 | } 79 | 80 | // Key returns the current element's key. 81 | // Does not modify the state of the iterator. 82 | func (iterator *Iterator[K, V]) Key() K { 83 | if iterator.node == nil { 84 | return *new(K) 85 | } 86 | return iterator.node.Key 87 | } 88 | 89 | // Begin resets the iterator to its initial state (one-before-first) 90 | // Call Next() to fetch the first element if any. 91 | func (iterator *Iterator[K, V]) Begin() { 92 | iterator.node = nil 93 | iterator.position = begin 94 | } 95 | 96 | // End moves the iterator past the last element (one-past-the-end). 97 | // Call Prev() to fetch the last element if any. 98 | func (iterator *Iterator[K, V]) End() { 99 | iterator.node = nil 100 | iterator.position = end 101 | } 102 | 103 | // First moves the iterator to the first element and returns true if there was a first element in the container. 104 | // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). 105 | // Modifies the state of the iterator 106 | func (iterator *Iterator[K, V]) First() bool { 107 | iterator.Begin() 108 | return iterator.Next() 109 | } 110 | 111 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 112 | // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). 113 | // Modifies the state of the iterator. 114 | func (iterator *Iterator[K, V]) Last() bool { 115 | iterator.End() 116 | return iterator.Prev() 117 | } 118 | -------------------------------------------------------------------------------- /trees/avltree/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package avltree 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | "github.com/daichi-m/go18ds/utils" 12 | ) 13 | 14 | func assertSerializationImplementation() { 15 | var _ containers.JSONSerializer = (*Tree[string, string])(nil) 16 | var _ containers.JSONDeserializer = (*Tree[string, string])(nil) 17 | } 18 | 19 | // ToJSON outputs the JSON representation of the tree. 20 | func (tree *Tree[K, V]) ToJSON() ([]byte, error) { 21 | elements := make(map[string]V) 22 | it := tree.Iterator() 23 | for it.Next() { 24 | elements[utils.ToString(it.Key())] = it.Value() 25 | } 26 | return json.Marshal(&elements) 27 | } 28 | 29 | // FromJSON populates the tree from the input JSON representation. 30 | func (tree *Tree[string, V]) FromJSON(data []byte) error { 31 | elements := make(map[string]V) 32 | err := json.Unmarshal(data, &elements) 33 | if err == nil { 34 | tree.Clear() 35 | for key, value := range elements { 36 | tree.Put(key, value) 37 | } 38 | } 39 | return err 40 | } 41 | -------------------------------------------------------------------------------- /trees/binaryheap/binaryheap.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package binaryheap implements a binary heap backed by array list. 6 | // 7 | // Comparator defines this heap as either min or max heap. 8 | // 9 | // Structure is not thread safe. 10 | // 11 | // References: http://en.wikipedia.org/wiki/Binary_heap 12 | package binaryheap 13 | 14 | import ( 15 | "fmt" 16 | "strings" 17 | 18 | "github.com/daichi-m/go18ds/lists/arraylist" 19 | "github.com/daichi-m/go18ds/trees" 20 | "github.com/daichi-m/go18ds/utils" 21 | ) 22 | 23 | func assertTreeImplementation() { 24 | var _ trees.Tree[int] = (*Heap[int])(nil) 25 | } 26 | 27 | // Heap holds elements in an array-list 28 | type Heap[T comparable] struct { 29 | list *arraylist.List[T] 30 | Comparator utils.Comparator[T] 31 | } 32 | 33 | // NewWith instantiates a new empty heap tree with the custom comparator. 34 | func NewWith[T comparable](comparator utils.Comparator[T]) *Heap[T] { 35 | return &Heap[T]{list: arraylist.New[T](), Comparator: comparator} 36 | } 37 | 38 | // NewWithIntComparator instantiates a new empty heap with the IntComparator, i.e. elements are of type int. 39 | func NewWithIntComparator() *Heap[int] { 40 | return &Heap[int]{list: arraylist.New[int](), Comparator: utils.NumberComparator[int]} 41 | } 42 | 43 | // NewWithStringComparator instantiates a new empty heap with the StringComparator, i.e. elements are of type string. 44 | func NewWithStringComparator() *Heap[string] { 45 | return &Heap[string]{list: arraylist.New[string](), Comparator: utils.StringComparator} 46 | } 47 | 48 | // Push adds a value onto the heap and bubbles it up accordingly. 49 | func (heap *Heap[T]) Push(values ...T) { 50 | if len(values) == 1 { 51 | heap.list.Add(values[0]) 52 | heap.bubbleUp() 53 | } else { 54 | // Reference: https://en.wikipedia.org/wiki/Binary_heap#Building_a_heap 55 | for _, value := range values { 56 | heap.list.Add(value) 57 | } 58 | size := heap.list.Size()/2 + 1 59 | for i := size; i >= 0; i-- { 60 | heap.bubbleDownIndex(i) 61 | } 62 | } 63 | } 64 | 65 | // Pop removes top element on heap and returns it, or nil if heap is empty. 66 | // Second return parameter is true, unless the heap was empty and there was nothing to pop. 67 | func (heap *Heap[T]) Pop() (value T, ok bool) { 68 | value, ok = heap.list.Get(0) 69 | if !ok { 70 | return 71 | } 72 | lastIndex := heap.list.Size() - 1 73 | heap.list.Swap(0, lastIndex) 74 | heap.list.Remove(lastIndex) 75 | heap.bubbleDown() 76 | return 77 | } 78 | 79 | // Peek returns top element on the heap without removing it, or nil if heap is empty. 80 | // Second return parameter is true, unless the heap was empty and there was nothing to peek. 81 | func (heap *Heap[T]) Peek() (value T, ok bool) { 82 | return heap.list.Get(0) 83 | } 84 | 85 | // Empty returns true if heap does not contain any elements. 86 | func (heap *Heap[T]) Empty() bool { 87 | return heap.list.Empty() 88 | } 89 | 90 | // Size returns number of elements within the heap. 91 | func (heap *Heap[T]) Size() int { 92 | return heap.list.Size() 93 | } 94 | 95 | // Clear removes all elements from the heap. 96 | func (heap *Heap[T]) Clear() { 97 | heap.list.Clear() 98 | } 99 | 100 | // Values returns all elements in the heap. 101 | func (heap *Heap[T]) Values() []T { 102 | return heap.list.Values() 103 | } 104 | 105 | // String returns a string representation of container 106 | func (heap *Heap[T]) String() string { 107 | str := "BinaryHeap\n" 108 | values := []string{} 109 | for _, value := range heap.list.Values() { 110 | values = append(values, fmt.Sprintf("%v", value)) 111 | } 112 | str += strings.Join(values, ", ") 113 | return str 114 | } 115 | 116 | // Performs the "bubble down" operation. This is to place the element that is at the root 117 | // of the heap in its correct place so that the heap maintains the min/max-heap order property. 118 | func (heap *Heap[T]) bubbleDown() { 119 | heap.bubbleDownIndex(0) 120 | } 121 | 122 | // Performs the "bubble down" operation. This is to place the element that is at the index 123 | // of the heap in its correct place so that the heap maintains the min/max-heap order property. 124 | func (heap *Heap[T]) bubbleDownIndex(index int) { 125 | size := heap.list.Size() 126 | for leftIndex := index<<1 + 1; leftIndex < size; leftIndex = index<<1 + 1 { 127 | rightIndex := index<<1 + 2 128 | smallerIndex := leftIndex 129 | leftValue, _ := heap.list.Get(leftIndex) 130 | rightValue, _ := heap.list.Get(rightIndex) 131 | if rightIndex < size && heap.Comparator(leftValue, rightValue) > 0 { 132 | smallerIndex = rightIndex 133 | } 134 | indexValue, _ := heap.list.Get(index) 135 | smallerValue, _ := heap.list.Get(smallerIndex) 136 | if heap.Comparator(indexValue, smallerValue) > 0 { 137 | heap.list.Swap(index, smallerIndex) 138 | } else { 139 | break 140 | } 141 | index = smallerIndex 142 | } 143 | } 144 | 145 | // Performs the "bubble up" operation. This is to place a newly inserted 146 | // element (i.e. last element in the list) in its correct place so that 147 | // the heap maintains the min/max-heap order property. 148 | func (heap *Heap[T]) bubbleUp() { 149 | index := heap.list.Size() - 1 150 | for parentIndex := (index - 1) >> 1; index > 0; parentIndex = (index - 1) >> 1 { 151 | indexValue, _ := heap.list.Get(index) 152 | parentValue, _ := heap.list.Get(parentIndex) 153 | if heap.Comparator(parentValue, indexValue) <= 0 { 154 | break 155 | } 156 | heap.list.Swap(index, parentIndex) 157 | index = parentIndex 158 | } 159 | } 160 | 161 | // Check that the index is within bounds of the list 162 | func (heap *Heap[T]) withinRange(index int) bool { 163 | return index >= 0 && index < heap.list.Size() 164 | } 165 | -------------------------------------------------------------------------------- /trees/binaryheap/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binaryheap 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.ReverseIteratorWithIndex[string] = (*Iterator[string])(nil) 11 | } 12 | 13 | // Iterator returns a stateful iterator whose values can be fetched by an index. 14 | type Iterator[T comparable] struct { 15 | heap *Heap[T] 16 | index int 17 | } 18 | 19 | // Iterator returns a stateful iterator whose values can be fetched by an index. 20 | func (heap *Heap[T]) Iterator() Iterator[T] { 21 | return Iterator[T]{heap: heap, index: -1} 22 | } 23 | 24 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 25 | // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 26 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 27 | // Modifies the state of the iterator. 28 | func (iterator *Iterator[T]) Next() bool { 29 | if iterator.index < iterator.heap.Size() { 30 | iterator.index++ 31 | } 32 | return iterator.heap.withinRange(iterator.index) 33 | } 34 | 35 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 36 | // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 37 | // Modifies the state of the iterator. 38 | func (iterator *Iterator[T]) Prev() bool { 39 | if iterator.index >= 0 { 40 | iterator.index-- 41 | } 42 | return iterator.heap.withinRange(iterator.index) 43 | } 44 | 45 | // Value returns the current element's value. 46 | // Does not modify the state of the iterator. 47 | func (iterator *Iterator[T]) Value() T { 48 | value, _ := iterator.heap.list.Get(iterator.index) 49 | return value 50 | } 51 | 52 | // Index returns the current element's index. 53 | // Does not modify the state of the iterator. 54 | func (iterator *Iterator[T]) Index() int { 55 | return iterator.index 56 | } 57 | 58 | // Begin resets the iterator to its initial state (one-before-first) 59 | // Call Next() to fetch the first element if any. 60 | func (iterator *Iterator[T]) Begin() { 61 | iterator.index = -1 62 | } 63 | 64 | // End moves the iterator past the last element (one-past-the-end). 65 | // Call Prev() to fetch the last element if any. 66 | func (iterator *Iterator[T]) End() { 67 | iterator.index = iterator.heap.Size() 68 | } 69 | 70 | // First moves the iterator to the first element and returns true if there was a first element in the container. 71 | // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 72 | // Modifies the state of the iterator. 73 | func (iterator *Iterator[T]) First() bool { 74 | iterator.Begin() 75 | return iterator.Next() 76 | } 77 | 78 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 79 | // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 80 | // Modifies the state of the iterator. 81 | func (iterator *Iterator[T]) Last() bool { 82 | iterator.End() 83 | return iterator.Prev() 84 | } 85 | -------------------------------------------------------------------------------- /trees/binaryheap/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binaryheap 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertSerializationImplementation() { 10 | var _ containers.JSONSerializer = (*Heap[int])(nil) 11 | var _ containers.JSONDeserializer = (*Heap[int])(nil) 12 | } 13 | 14 | // ToJSON outputs the JSON representation of the heap. 15 | func (heap *Heap[T]) ToJSON() ([]byte, error) { 16 | return heap.list.ToJSON() 17 | } 18 | 19 | // FromJSON populates the heap from the input JSON representation. 20 | func (heap *Heap[T]) FromJSON(data []byte) error { 21 | return heap.list.FromJSON(data) 22 | } 23 | -------------------------------------------------------------------------------- /trees/btree/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package btree 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | "github.com/daichi-m/go18ds/utils" 12 | ) 13 | 14 | func assertSerializationImplementation() { 15 | var _ containers.JSONSerializer = (*Tree[string, string])(nil) 16 | var _ containers.JSONDeserializer = (*Tree[string, string])(nil) 17 | } 18 | 19 | // ToJSON outputs the JSON representation of the tree. 20 | func (tree *Tree[K, V]) ToJSON() ([]byte, error) { 21 | elements := make(map[string]V) 22 | it := tree.Iterator() 23 | for it.Next() { 24 | elements[utils.ToString(it.Key())] = it.Value() 25 | } 26 | return json.Marshal(&elements) 27 | } 28 | 29 | // FromJSON populates the tree from the input JSON representation. 30 | func (tree *Tree[string, V]) FromJSON(data []byte) error { 31 | elements := make(map[string]V) 32 | err := json.Unmarshal(data, &elements) 33 | if err == nil { 34 | tree.Clear() 35 | for key, value := range elements { 36 | tree.Put(key, value) 37 | } 38 | } 39 | return err 40 | } 41 | -------------------------------------------------------------------------------- /trees/redblacktree/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package redblacktree 6 | 7 | import "github.com/daichi-m/go18ds/containers" 8 | 9 | func assertIteratorImplementation() { 10 | var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil) 11 | } 12 | 13 | // Iterator holding the iterator's state 14 | type Iterator[K comparable, V comparable] struct { 15 | tree *Tree[K, V] 16 | node *Node[K, V] 17 | position position 18 | } 19 | 20 | type position byte 21 | 22 | const ( 23 | begin, between, end position = 0, 1, 2 24 | ) 25 | 26 | // Iterator returns a stateful iterator whose elements are key/value pairs. 27 | func (tree *Tree[K, V]) Iterator() Iterator[K, V] { 28 | return Iterator[K, V]{tree: tree, node: nil, position: begin} 29 | } 30 | 31 | // IteratorAt returns a stateful iterator whose elements are key/value pairs that is initialised at a particular node. 32 | func (tree *Tree[K, V]) IteratorAt(node *Node[K, V]) Iterator[K, V] { 33 | return Iterator[K, V]{tree: tree, node: node, position: between} 34 | } 35 | 36 | // Next moves the iterator to the next element and returns true if there was a next element in the container. 37 | // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). 38 | // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 39 | // Modifies the state of the iterator. 40 | func (iterator *Iterator[K, V]) Next() bool { 41 | if iterator.position == end { 42 | goto end 43 | } 44 | if iterator.position == begin { 45 | left := iterator.tree.Left() 46 | if left == nil { 47 | goto end 48 | } 49 | iterator.node = left 50 | goto between 51 | } 52 | if iterator.node.Right != nil { 53 | iterator.node = iterator.node.Right 54 | for iterator.node.Left != nil { 55 | iterator.node = iterator.node.Left 56 | } 57 | goto between 58 | } 59 | if iterator.node.Parent != nil { 60 | node := iterator.node 61 | for iterator.node.Parent != nil { 62 | iterator.node = iterator.node.Parent 63 | if iterator.tree.Comparator(node.Key, iterator.node.Key) <= 0 { 64 | goto between 65 | } 66 | } 67 | } 68 | 69 | end: 70 | iterator.node = nil 71 | iterator.position = end 72 | return false 73 | 74 | between: 75 | iterator.position = between 76 | return true 77 | } 78 | 79 | // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 80 | // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). 81 | // Modifies the state of the iterator. 82 | func (iterator *Iterator[K, V]) Prev() bool { 83 | if iterator.position == begin { 84 | goto begin 85 | } 86 | if iterator.position == end { 87 | right := iterator.tree.Right() 88 | if right == nil { 89 | goto begin 90 | } 91 | iterator.node = right 92 | goto between 93 | } 94 | if iterator.node.Left != nil { 95 | iterator.node = iterator.node.Left 96 | for iterator.node.Right != nil { 97 | iterator.node = iterator.node.Right 98 | } 99 | goto between 100 | } 101 | if iterator.node.Parent != nil { 102 | node := iterator.node 103 | for iterator.node.Parent != nil { 104 | iterator.node = iterator.node.Parent 105 | if iterator.tree.Comparator(node.Key, iterator.node.Key) >= 0 { 106 | goto between 107 | } 108 | } 109 | } 110 | 111 | begin: 112 | iterator.node = nil 113 | iterator.position = begin 114 | return false 115 | 116 | between: 117 | iterator.position = between 118 | return true 119 | } 120 | 121 | // Value returns the current element's value. 122 | // Does not modify the state of the iterator. 123 | func (iterator *Iterator[K, V]) Value() V { 124 | return iterator.node.Value 125 | } 126 | 127 | // Key returns the current element's key. 128 | // Does not modify the state of the iterator. 129 | func (iterator *Iterator[K, V]) Key() K { 130 | return iterator.node.Key 131 | } 132 | 133 | // Begin resets the iterator to its initial state (one-before-first) 134 | // Call Next() to fetch the first element if any. 135 | func (iterator *Iterator[K, V]) Begin() { 136 | iterator.node = nil 137 | iterator.position = begin 138 | } 139 | 140 | // End moves the iterator past the last element (one-past-the-end). 141 | // Call Prev() to fetch the last element if any. 142 | func (iterator *Iterator[K, V]) End() { 143 | iterator.node = nil 144 | iterator.position = end 145 | } 146 | 147 | // First moves the iterator to the first element and returns true if there was a first element in the container. 148 | // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). 149 | // Modifies the state of the iterator 150 | func (iterator *Iterator[K, V]) First() bool { 151 | iterator.Begin() 152 | return iterator.Next() 153 | } 154 | 155 | // Last moves the iterator to the last element and returns true if there was a last element in the container. 156 | // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). 157 | // Modifies the state of the iterator. 158 | func (iterator *Iterator[K, V]) Last() bool { 159 | iterator.End() 160 | return iterator.Prev() 161 | } 162 | -------------------------------------------------------------------------------- /trees/redblacktree/serialization.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package redblacktree 6 | 7 | import ( 8 | "encoding/json" 9 | 10 | "github.com/daichi-m/go18ds/containers" 11 | "github.com/daichi-m/go18ds/utils" 12 | ) 13 | 14 | func assertSerializationImplementation() { 15 | var _ containers.JSONSerializer = (*Tree[string, string])(nil) 16 | var _ containers.JSONDeserializer = (*Tree[string, string])(nil) 17 | } 18 | 19 | // ToJSON outputs the JSON representation of the tree. 20 | func (tree *Tree[K, V]) ToJSON() ([]byte, error) { 21 | elements := make(map[string]interface{}) 22 | it := tree.Iterator() 23 | for it.Next() { 24 | elements[utils.ToString(it.Key())] = it.Value() 25 | } 26 | return json.Marshal(&elements) 27 | } 28 | 29 | // FromJSON populates the tree from the input JSON representation. 30 | func (tree *Tree[string, V]) FromJSON(data []byte) error { 31 | elements := make(map[string]V) 32 | err := json.Unmarshal(data, &elements) 33 | if err == nil { 34 | tree.Clear() 35 | for key, value := range elements { 36 | tree.Put(key, value) 37 | } 38 | } 39 | return err 40 | } 41 | -------------------------------------------------------------------------------- /trees/trees.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package trees provides an abstract Tree interface. 6 | // 7 | // In computer science, a tree is a widely used abstract data type (ADT) or data structure implementing this ADT that simulates a hierarchical tree structure, with a root value and subtrees of children with a parent node, represented as a set of linked nodes. 8 | // 9 | // Reference: https://en.wikipedia.org/wiki/Tree_%28data_structure%29 10 | package trees 11 | 12 | import "github.com/daichi-m/go18ds/containers" 13 | 14 | // Tree interface that all trees implement 15 | type Tree[T comparable] interface { 16 | containers.Container[T] 17 | // Empty() bool 18 | // Size() int 19 | // Clear() 20 | // Values() []interface{} 21 | } 22 | -------------------------------------------------------------------------------- /utils/comparator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "time" 9 | ) 10 | 11 | // Comparator will make type assertion (see IntComparator for example), 12 | // which will panic if a or b are not of the asserted type. 13 | // 14 | // Should return a number: 15 | // negative , if a < b 16 | // zero , if a == b 17 | // positive , if a > b 18 | type Comparator[T comparable] func(a, b T) int 19 | 20 | func assertComparatorImplementation() { 21 | var _ Comparator[string] = StringComparator 22 | 23 | var _ Comparator[int] = NumberComparator[int] 24 | var _ Comparator[int8] = NumberComparator[int8] 25 | var _ Comparator[int16] = NumberComparator[int16] 26 | var _ Comparator[int32] = NumberComparator[int32] 27 | var _ Comparator[int64] = NumberComparator[int64] 28 | var _ Comparator[uint8] = NumberComparator[uint8] 29 | var _ Comparator[uint16] = NumberComparator[uint16] 30 | var _ Comparator[uint32] = NumberComparator[uint32] 31 | var _ Comparator[uint64] = NumberComparator[uint64] 32 | 33 | var _ Comparator[float32] = NumberComparator[float32] 34 | var _ Comparator[float64] = NumberComparator[float64] 35 | var _ Comparator[byte] = NumberComparator[byte] 36 | var _ Comparator[rune] = NumberComparator[rune] 37 | 38 | var _ Comparator[time.Time] = TimeComparator 39 | } 40 | 41 | // StringComparator provides a fast comparison on strings 42 | func StringComparator(s1, s2 string) int { 43 | min := len(s2) 44 | if len(s1) < len(s2) { 45 | min = len(s1) 46 | } 47 | diff := 0 48 | for i := 0; i < min && diff == 0; i++ { 49 | diff = int(s1[i]) - int(s2[i]) 50 | } 51 | if diff == 0 { 52 | diff = len(s1) - len(s2) 53 | } 54 | if diff < 0 { 55 | return -1 56 | } 57 | if diff > 0 { 58 | return 1 59 | } 60 | return 0 61 | } 62 | 63 | // IntComparator provides a basic comparison on int 64 | func NumberComparator[T Number](a, b T) int { 65 | switch { 66 | case a > b: 67 | return 1 68 | case a < b: 69 | return -1 70 | default: 71 | return 0 72 | } 73 | } 74 | 75 | // TimeComparator provides a basic comparison on time.Time 76 | func TimeComparator(a, b time.Time) int { 77 | switch { 78 | case a.After(b): 79 | return 1 80 | case a.Before(b): 81 | return -1 82 | default: 83 | return 0 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /utils/comparator_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "testing" 9 | "time" 10 | ) 11 | 12 | func TestIntComparator(t *testing.T) { 13 | // i1,i2,expected 14 | tests := []struct { 15 | i1, i2 int 16 | expected int 17 | }{ 18 | {1, 1, 0}, 19 | {1, 2, -1}, 20 | {2, 1, 1}, 21 | {11, 22, -1}, 22 | {0, 0, 0}, 23 | {1, 0, 1}, 24 | {0, 1, -1}, 25 | } 26 | 27 | for _, test := range tests { 28 | t.Run("IntCompare", func(tt *testing.T) { 29 | actual := NumberComparator(test.i1, test.i2) 30 | expected := test.expected 31 | if actual != expected { 32 | tt.Errorf("Got %v expected %v", actual, expected) 33 | } 34 | }) 35 | } 36 | } 37 | 38 | func TestStringComparator(t *testing.T) { 39 | // s1,s2,expected 40 | tests := []struct { 41 | s1, s2 string 42 | expected int 43 | }{ 44 | {"a", "a", 0}, 45 | {"a", "b", -1}, 46 | {"b", "a", 1}, 47 | {"aa", "aab", -1}, 48 | {"", "", 0}, 49 | {"a", "", 1}, 50 | {"", "a", -1}, 51 | {"", "aaaaaaa", -1}, 52 | } 53 | 54 | for _, test := range tests { 55 | t.Run("StringCompare", func(tt *testing.T) { 56 | actual := StringComparator(test.s1, test.s2) 57 | expected := test.expected 58 | if actual != expected { 59 | tt.Errorf("Got %v expected %v", actual, expected) 60 | } 61 | }) 62 | } 63 | } 64 | 65 | func TestTimeComparator(t *testing.T) { 66 | now := time.Now() 67 | 68 | // i1,i2,expected 69 | tests := []struct { 70 | t1, t2 time.Time 71 | expected int 72 | }{ 73 | {now, now, 0}, 74 | {now.Add(24 * 7 * 2 * time.Hour), now, 1}, 75 | {now, now.Add(24 * 7 * 2 * time.Hour), -1}, 76 | } 77 | 78 | for _, test := range tests { 79 | t.Run("TimeCompare", func(tt *testing.T) { 80 | actual := TimeComparator(test.t1, test.t2) 81 | expected := test.expected 82 | if actual != expected { 83 | tt.Errorf("Got %v expected %v", actual, expected) 84 | } 85 | }) 86 | } 87 | } 88 | 89 | func TestCustomComparator(t *testing.T) { 90 | type Custom struct { 91 | id int 92 | name string 93 | } 94 | 95 | sortByID := func(c1, c2 Custom) int { 96 | switch { 97 | case c1.id > c2.id: 98 | return 1 99 | case c1.id < c2.id: 100 | return -1 101 | default: 102 | return 0 103 | } 104 | } 105 | 106 | // o1,o2,expected 107 | tests := []struct { 108 | c1, c2 Custom 109 | expected int 110 | }{ 111 | {Custom{1, "a"}, Custom{1, "a"}, 0}, 112 | {Custom{1, "a"}, Custom{2, "b"}, -1}, 113 | {Custom{2, "b"}, Custom{1, "a"}, 1}, 114 | {Custom{1, "a"}, Custom{1, "b"}, 0}, 115 | } 116 | 117 | for _, test := range tests { 118 | t.Run("CustomCompare", func(tt *testing.T) { 119 | actual := sortByID(test.c1, test.c2) 120 | expected := test.expected 121 | if actual != expected { 122 | tt.Errorf("Got %v expected %v", actual, expected) 123 | } 124 | }) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /utils/constraints.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | /* Placeholder for proposed "constraints" std package 8 | * https://pkg.go.dev/constraints 9 | */ 10 | 11 | // Signed is a constraint that permits any signed integer type. 12 | // If future releases of Go add new predeclared signed integer types, 13 | // this constraint will be modified to include them. 14 | type Signed interface { 15 | ~int | ~int8 | ~int16 | ~int32 | ~int64 16 | } 17 | 18 | // Unsigned is a constraint that permits any unsigned integer type. 19 | // If future releases of Go add new predeclared unsigned integer types, 20 | // this constraint will be modified to include them. 21 | type Unsigned interface { 22 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr 23 | } 24 | 25 | // Integer is a constraint that permits any integer type. 26 | // If future releases of Go add new predeclared integer types, 27 | // this constraint will be modified to include them. 28 | type Integer interface { 29 | Signed | Unsigned 30 | } 31 | 32 | // Float is a constraint that permits any floating-point type. 33 | // If future releases of Go add new predeclared floating-point types, 34 | // this constraint will be modified to include them. 35 | type Float interface { 36 | ~float32 | ~float64 37 | } 38 | 39 | // Complex is a constraint that permits any complex numeric type. 40 | // If future releases of Go add new predeclared complex numeric types, 41 | // this constraint will be modified to include them. 42 | type Complex interface { 43 | ~complex64 | ~complex128 44 | } 45 | 46 | // Ordered is a constraint that permits any ordered type: any type 47 | // that supports the operators < <= >= >. 48 | // If future releases of Go add new ordered types, 49 | // this constraint will be modified to include them. 50 | type Ordered interface { 51 | Integer | Float | ~string 52 | } 53 | 54 | type Number interface { 55 | Integer | Float 56 | } 57 | -------------------------------------------------------------------------------- /utils/sort.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import "sort" 8 | 9 | // Sort sorts values (in-place) with respect to the given comparator. 10 | // 11 | // Uses Go's sort (hybrid of quicksort for large and then insertion sort for smaller slices). 12 | func Sort[T comparable](values []T, comparator Comparator[T]) { 13 | sort.Sort(sortable[T]{values, comparator}) 14 | } 15 | 16 | type sortable[T comparable] struct { 17 | values []T 18 | comparator Comparator[T] 19 | } 20 | 21 | func (s sortable[T]) Len() int { 22 | return len(s.values) 23 | } 24 | func (s sortable[T]) Swap(i, j int) { 25 | s.values[i], s.values[j] = s.values[j], s.values[i] 26 | } 27 | func (s sortable[T]) Less(i, j int) bool { 28 | return s.comparator(s.values[i], s.values[j]) < 0 29 | } 30 | -------------------------------------------------------------------------------- /utils/sort_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | ) 11 | 12 | func TestSortInts(t *testing.T) { 13 | ints := []int{} 14 | ints = append(ints, 4) 15 | ints = append(ints, 1) 16 | ints = append(ints, 2) 17 | ints = append(ints, 3) 18 | 19 | Sort(ints, NumberComparator[int]) 20 | 21 | for i := 1; i < len(ints); i++ { 22 | if ints[i-1] > ints[i] { 23 | t.Errorf("Not sorted!") 24 | } 25 | } 26 | } 27 | 28 | func TestSortStrings(t *testing.T) { 29 | strings := []string{} 30 | strings = append(strings, "d") 31 | strings = append(strings, "a") 32 | strings = append(strings, "b") 33 | strings = append(strings, "c") 34 | 35 | Sort(strings, StringComparator) 36 | 37 | for i := 1; i < len(strings); i++ { 38 | if strings[i-1] > strings[i] { 39 | t.Errorf("Not sorted!") 40 | } 41 | } 42 | } 43 | 44 | func TestSortStructs(t *testing.T) { 45 | type User struct { 46 | id int 47 | name string 48 | } 49 | 50 | sortByID := func(c1, c2 User) int { 51 | switch { 52 | case c1.id > c2.id: 53 | return 1 54 | case c1.id < c2.id: 55 | return -1 56 | default: 57 | return 0 58 | } 59 | } 60 | 61 | // o1,o2,expected 62 | users := []User{ 63 | {4, "John"}, 64 | {1, "Jane"}, 65 | {3, "Jack"}, 66 | {2, "Jill"}, 67 | } 68 | 69 | Sort(users, sortByID) 70 | 71 | for i := 1; i < len(users); i++ { 72 | if users[i-1].id > users[i].id { 73 | t.Errorf("Not sorted!") 74 | } 75 | } 76 | } 77 | 78 | func TestSortRandom(t *testing.T) { 79 | ints := []int{} 80 | for i := 0; i < 10000; i++ { 81 | ints = append(ints, rand.Int()) 82 | } 83 | Sort(ints, NumberComparator[int]) 84 | for i := 1; i < len(ints); i++ { 85 | if ints[i-1] > ints[i] { 86 | t.Errorf("Not sorted!") 87 | } 88 | } 89 | } 90 | 91 | func BenchmarkGoSortRandom(b *testing.B) { 92 | b.StopTimer() 93 | ints := []int{} 94 | for i := 0; i < 100000; i++ { 95 | ints = append(ints, rand.Int()) 96 | } 97 | b.StartTimer() 98 | Sort(ints, NumberComparator[int]) 99 | b.StopTimer() 100 | } 101 | -------------------------------------------------------------------------------- /utils/utils.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package utils provides common utility functions. 6 | // 7 | // Provided functionalities: 8 | // - sorting 9 | // - comparators 10 | package utils 11 | 12 | import ( 13 | "fmt" 14 | "strconv" 15 | ) 16 | 17 | // ToString converts a value to string. 18 | func ToString(value interface{}) string { 19 | switch value := value.(type) { 20 | case string: 21 | return value 22 | case int8: 23 | return strconv.FormatInt(int64(value), 10) 24 | case int16: 25 | return strconv.FormatInt(int64(value), 10) 26 | case int32: 27 | return strconv.FormatInt(int64(value), 10) 28 | case int64: 29 | return strconv.FormatInt(int64(value), 10) 30 | case uint8: 31 | return strconv.FormatUint(uint64(value), 10) 32 | case uint16: 33 | return strconv.FormatUint(uint64(value), 10) 34 | case uint32: 35 | return strconv.FormatUint(uint64(value), 10) 36 | case uint64: 37 | return strconv.FormatUint(uint64(value), 10) 38 | case float32: 39 | return strconv.FormatFloat(float64(value), 'g', -1, 64) 40 | case float64: 41 | return strconv.FormatFloat(float64(value), 'g', -1, 64) 42 | case bool: 43 | return strconv.FormatBool(value) 44 | default: 45 | return fmt.Sprintf("%+v", value) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /utils/utils_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "strings" 9 | "testing" 10 | ) 11 | 12 | func TestToStringInts(t *testing.T) { 13 | var value interface{} 14 | 15 | value = int8(1) 16 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 17 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 18 | } 19 | 20 | value = int16(1) 21 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 22 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 23 | } 24 | 25 | value = int32(1) 26 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 27 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 28 | } 29 | 30 | value = int64(1) 31 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 32 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 33 | } 34 | 35 | value = rune(1) 36 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 37 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 38 | } 39 | } 40 | 41 | func TestToStringUInts(t *testing.T) { 42 | var value interface{} 43 | 44 | value = uint8(1) 45 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 46 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 47 | } 48 | 49 | value = uint16(1) 50 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 51 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 52 | } 53 | 54 | value = uint32(1) 55 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 56 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 57 | } 58 | 59 | value = uint64(1) 60 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 61 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 62 | } 63 | 64 | value = byte(1) 65 | if actualValue, expectedValue := ToString(value), "1"; actualValue != expectedValue { 66 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 67 | } 68 | } 69 | 70 | func TestToStringFloats(t *testing.T) { 71 | var value interface{} 72 | 73 | value = float32(1.123456) 74 | if actualValue, expectedValue := ToString(value), "1.123456"; !strings.HasPrefix(actualValue, expectedValue) { 75 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 76 | } 77 | value = float64(1.123456) 78 | if actualValue, expectedValue := ToString(value), "1.123456"; !strings.HasPrefix(actualValue, expectedValue) { 79 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 80 | } 81 | } 82 | 83 | func TestToStringOther(t *testing.T) { 84 | var value interface{} 85 | 86 | value = "abc" 87 | if actualValue, expectedValue := ToString(value), "abc"; actualValue != expectedValue { 88 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 89 | } 90 | 91 | value = true 92 | if actualValue, expectedValue := ToString(value), "true"; actualValue != expectedValue { 93 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 94 | } 95 | 96 | type T struct { 97 | id int 98 | name string 99 | } 100 | 101 | if actualValue, expectedValue := ToString(T{1, "abc"}), "{id:1 name:abc}"; actualValue != expectedValue { 102 | t.Errorf("Got %v expected %v", actualValue, expectedValue) 103 | } 104 | } 105 | --------------------------------------------------------------------------------