# gods **Repository Path**: TracingSource/gods ## Basic Information - **Project Name**: gods - **Description**: GoDS (Go Data Structures) https://github.com/emirpasic/gods 基本 master 的 9f3e98d84ae0755196be26ae099772039420c539 提交, 可视作 v1.18.1 版本 - **Primary Language**: Go - **License**: BSD-2-Clause - **Default Branch**: source-read-v1.18.1 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-05-21 - **Last Updated**: 2024-07-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # GoDS (Go Data Structures) Implementation of various data structures and algorithms in Go. ## Data Structures - [GoDS (Go Data Structures)](#gods-go-data-structures) - [Data Structures](#data-structures) - [Containers](#containers) - [Functions](#functions) - [Comparator](#comparator) - [Iterator](#iterator) - [IteratorWithIndex](#iteratorwithindex) - [IteratorWithKey](#iteratorwithkey) - [ReverseIteratorWithIndex](#reverseiteratorwithindex) - [ReverseIteratorWithKey](#reverseiteratorwithkey) - [Enumerable](#enumerable) - [EnumerableWithIndex](#enumerablewithindex) - [EnumerableWithKey](#enumerablewithkey) - [Serialization](#serialization) - [JSONSerializer](#jsonserializer) - [JSONDeserializer](#jsondeserializer) - [Sort](#sort) - [Container](#container) - [Appendix](#appendix) - [Motivation](#motivation) - [Goals](#goals) - [Testing and Benchmarking](#testing-and-benchmarking) - [Contributing](#contributing) ## Containers 所有数据结构都实现了`Container`接口. ```go type Container interface { Empty() bool Size() int Clear() Values() []interface{} String() string } ``` Containers are either ordered or unordered. All ordered containers provide [stateful iterators](#iterator) and some of them allow [enumerable functions](#enumerable). ## Functions Various helper functions used throughout the library. ### Comparator Some data structures (e.g. TreeMap, TreeSet) require a comparator function to automatically keep their elements sorted upon insertion. This comparator is necessary during the initalization. Comparator is defined as: Return values (int): ```go negative , if a < b zero , if a == b positive , if a > b ``` Comparator signature: ```go type Comparator func(a, b interface{}) int ``` All common comparators for builtin types are included in the library: Writing custom comparators is easy: ```go package main import ( "fmt" "github.com/emirpasic/gods/sets/treeset" ) type User struct { id int name string } // Custom comparator (sort by IDs) func byID(a, b interface{}) int { // Type assertion, program will panic if this is not respected c1 := a.(User) c2 := b.(User) switch { case c1.id > c2.id: return 1 case c1.id < c2.id: return -1 default: return 0 } } func main() { set := treeset.NewWith(byID) set.Add(User{2, "Second"}) set.Add(User{3, "Third"}) set.Add(User{1, "First"}) set.Add(User{4, "Fourth"}) fmt.Println(set) // {1 First}, {2 Second}, {3 Third}, {4 Fourth} } ``` ### Iterator All ordered containers have stateful iterators. Typically an iterator is obtained by _Iterator()_ function of an ordered container. Once obtained, iterator's _Next()_ function moves the iterator to the next element and returns true if there was a next element. If there was an element, then element's can be obtained by iterator's _Value()_ function. Depending on the ordering type, it's position can be obtained by iterator's _Index()_ or _Key()_ functions. Some containers even provide reversible iterators, essentially the same, but provide another extra _Prev()_ function that moves the iterator to the previous element and returns true if there was a previous element. Note: it is unsafe to remove elements from container while iterating. #### IteratorWithIndex An [iterator](#iterator) whose elements are referenced by an index. Typical usage: ```go it := list.Iterator() for it.Next() { index, value := it.Index(), it.Value() ... } ``` Other usages: ```go if it.First() { firstIndex, firstValue := it.Index(), it.Value() ... } ``` ```go for it.Begin(); it.Next(); { ... } ``` Seeking to a specific element: ```go // Seek function, i.e. find element starting with "b" seek := func(index int, value interface{}) bool { return strings.HasSuffix(value.(string), "b") } // Seek to the condition and continue traversal from that point (forward). // assumes it.Begin() was called. for found := it.NextTo(seek); found; found = it.Next() { index, value := it.Index(), it.Value() ... } ``` #### IteratorWithKey An [iterator](#iterator) whose elements are referenced by a key. Typical usage: ```go it := tree.Iterator() for it.Next() { key, value := it.Key(), it.Value() ... } ``` Other usages: ```go if it.First() { firstKey, firstValue := it.Key(), it.Value() ... } ``` ```go for it.Begin(); it.Next(); { ... } ``` Seeking to a specific element from the current iterator position: ```go // Seek function, i.e. find element starting with "b" seek := func(key interface{}, value interface{}) bool { return strings.HasSuffix(value.(string), "b") } // Seek to the condition and continue traversal from that point (forward). // assumes it.Begin() was called. for found := it.NextTo(seek); found; found = it.Next() { key, value := it.Key(), it.Value() ... } ``` #### ReverseIteratorWithIndex An [iterator](#iterator) whose elements are referenced by an index. Provides all functions as [IteratorWithIndex](#iteratorwithindex), but can also be used for reverse iteration. Typical usage of iteration in reverse: ```go it := list.Iterator() for it.End(); it.Prev(); { index, value := it.Index(), it.Value() ... } ``` Other usages: ```go if it.Last() { lastIndex, lastValue := it.Index(), it.Value() ... } ``` Seeking to a specific element: ```go // Seek function, i.e. find element starting with "b" seek := func(index int, value interface{}) bool { return strings.HasSuffix(value.(string), "b") } // Seek to the condition and continue traversal from that point (in reverse). // assumes it.End() was called. for found := it.PrevTo(seek); found; found = it.Prev() { index, value := it.Index(), it.Value() ... } ``` #### ReverseIteratorWithKey An [iterator](#iterator) whose elements are referenced by a key. Provides all functions as [IteratorWithKey](#iteratorwithkey), but can also be used for reverse iteration. Typical usage of iteration in reverse: ```go it := tree.Iterator() for it.End(); it.Prev(); { key, value := it.Key(), it.Value() ... } ``` Other usages: ```go if it.Last() { lastKey, lastValue := it.Key(), it.Value() ... } ``` ```go // Seek function, i.e. find element starting with "b" seek := func(key interface{}, value interface{}) bool { return strings.HasSuffix(value.(string), "b") } // Seek to the condition and continue traversal from that point (in reverse). // assumes it.End() was called. for found := it.PrevTo(seek); found; found = it.Prev() { key, value := it.Key(), it.Value() ... } ``` ### Enumerable Enumerable functions for ordered containers that implement [EnumerableWithIndex](#enumerablewithindex) or [EnumerableWithKey](#enumerablewithkey) interfaces. #### EnumerableWithIndex [Enumerable](#enumerable) functions for ordered containers whose values can be fetched by an index. **Each** Calls the given function once for each element, passing that element's index and value. ```go Each(func(index int, value interface{})) ``` **Map** Invokes the given function once for each element and returns a container containing the values returned by the given function. ```go Map(func(index int, value interface{}) interface{}) Container ``` **Select** Returns a new container containing all elements for which the given function returns a true value. ```go Select(func(index int, value interface{}) bool) Container ``` **Any** Passes each element of the container to the given function and returns true if the function ever returns true for any element. ```go Any(func(index int, value interface{}) bool) bool ``` **All** Passes each element of the container to the given function and returns true if the function returns true for all elements. ```go All(func(index int, value interface{}) bool) bool ``` **Find** Passes each element of the container to the given function and returns the first (index,value) for which the function is true or -1,nil otherwise if no element matches the criteria. ```go Find(func(index int, value interface{}) bool) (int, interface{})} ``` **Example:** ```go package main import ( "fmt" "github.com/emirpasic/gods/sets/treeset" ) func printSet(txt string, set *treeset.Set) { fmt.Print(txt, "[ ") set.Each(func(index int, value interface{}) { fmt.Print(value, " ") }) fmt.Println("]") } func main() { set := treeset.NewWithIntComparator() set.Add(2, 3, 4, 2, 5, 6, 7, 8) printSet("Initial", set) // [ 2 3 4 5 6 7 8 ] even := set.Select(func(index int, value interface{}) bool { return value.(int)%2 == 0 }) printSet("Even numbers", even) // [ 2 4 6 8 ] foundIndex, foundValue := set.Find(func(index int, value interface{}) bool { return value.(int)%2 == 0 && value.(int)%3 == 0 }) if foundIndex != -1 { fmt.Println("Number divisible by 2 and 3 found is", foundValue, "at index", foundIndex) // value: 6, index: 4 } square := set.Map(func(index int, value interface{}) interface{} { return value.(int) * value.(int) }) printSet("Numbers squared", square) // [ 4 9 16 25 36 49 64 ] bigger := set.Any(func(index int, value interface{}) bool { return value.(int) > 5 }) fmt.Println("Set contains a number bigger than 5 is ", bigger) // true positive := set.All(func(index int, value interface{}) bool { return value.(int) > 0 }) fmt.Println("All numbers are positive is", positive) // true evenNumbersSquared := set.Select(func(index int, value interface{}) bool { return value.(int)%2 == 0 }).Map(func(index int, value interface{}) interface{} { return value.(int) * value.(int) }) printSet("Chaining", evenNumbersSquared) // [ 4 16 36 64 ] } ``` #### EnumerableWithKey Enumerable functions for ordered containers whose values whose elements are key/value pairs. **Each** Calls the given function once for each element, passing that element's key and value. ```go Each(func(key interface{}, value interface{})) ``` **Map** Invokes the given function once for each element and returns a container containing the values returned by the given function as key/value pairs. ```go Map(func(key interface{}, value interface{}) (interface{}, interface{})) Container ``` **Select** Returns a new container containing all elements for which the given function returns a true value. ```go Select(func(key interface{}, value interface{}) bool) Container ``` **Any** Passes each element of the container to the given function and returns true if the function ever returns true for any element. ```go Any(func(key interface{}, value interface{}) bool) bool ``` **All** Passes each element of the container to the given function and returns true if the function returns true for all elements. ```go All(func(key interface{}, value interface{}) bool) bool ``` **Find** Passes each element of the container to the given function and returns the first (key,value) for which the function is true or nil,nil otherwise if no element matches the criteria. ```go Find(func(key interface{}, value interface{}) bool) (interface{}, interface{}) ``` **Example:** ```go package main import ( "fmt" "github.com/emirpasic/gods/maps/treemap" ) func printMap(txt string, m *treemap.Map) { fmt.Print(txt, " { ") m.Each(func(key interface{}, value interface{}) { fmt.Print(key, ":", value, " ") }) fmt.Println("}") } func main() { m := treemap.NewWithStringComparator() m.Put("g", 7) m.Put("f", 6) m.Put("e", 5) m.Put("d", 4) m.Put("c", 3) m.Put("b", 2) m.Put("a", 1) printMap("Initial", m) // { a:1 b:2 c:3 d:4 e:5 f:6 g:7 } even := m.Select(func(key interface{}, value interface{}) bool { return value.(int) % 2 == 0 }) printMap("Elements with even values", even) // { b:2 d:4 f:6 } foundKey, foundValue := m.Find(func(key interface{}, value interface{}) bool { return value.(int) % 2 == 0 && value.(int) % 3 == 0 }) if foundKey != nil { fmt.Println("Element with value divisible by 2 and 3 found is", foundValue, "with key", foundKey) // value: 6, index: 4 } square := m.Map(func(key interface{}, value interface{}) (interface{}, interface{}) { return key.(string) + key.(string), value.(int) * value.(int) }) printMap("Elements' values squared and letters duplicated", square) // { aa:1 bb:4 cc:9 dd:16 ee:25 ff:36 gg:49 } bigger := m.Any(func(key interface{}, value interface{}) bool { return value.(int) > 5 }) fmt.Println("Map contains element whose value is bigger than 5 is", bigger) // true positive := m.All(func(key interface{}, value interface{}) bool { return value.(int) > 0 }) fmt.Println("All map's elements have positive values is", positive) // true evenNumbersSquared := m.Select(func(key interface{}, value interface{}) bool { return value.(int) % 2 == 0 }).Map(func(key interface{}, value interface{}) (interface{}, interface{}) { return key, value.(int) * value.(int) }) printMap("Chaining", evenNumbersSquared) // { b:4 d:16 f:36 } } ``` ### Serialization All data structures can be serialized (marshalled) and deserialized (unmarshalled). Currently, only JSON support is available. #### JSONSerializer Outputs the container into its JSON representation. Typical usage for key-value structures: ```go package main import ( "encoding/json" "fmt" "github.com/emirpasic/gods/maps/hashmap" ) func main() { m := hashmap.New() m.Put("a", "1") m.Put("b", "2") m.Put("c", "3") bytes, err := json.Marshal(m) // Same as "m.ToJSON(m)" if err != nil { fmt.Println(err) } fmt.Println(string(bytes)) // {"a":"1","b":"2","c":"3"} } ``` Typical usage for value-only structures: ```go package main import ( "encoding/json" "fmt" "github.com/emirpasic/gods/lists/arraylist" ) func main() { list := arraylist.New() list.Add("a", "b", "c") bytes, err := json.Marshal(list) // Same as "list.ToJSON(list)" if err != nil { fmt.Println(err) } fmt.Println(string(bytes)) // ["a","b","c"] } ``` #### JSONDeserializer Populates the container with elements from the input JSON representation. Typical usage for key-value structures: ```go package main import ( "encoding/json" "fmt" "github.com/emirpasic/gods/maps/hashmap" ) func main() { hm := hashmap.New() bytes := []byte(`{"a":"1","b":"2"}`) err := json.Unmarshal(bytes, &hm) // Same as "hm.FromJSON(bytes)" if err != nil { fmt.Println(err) } fmt.Println(hm) // HashMap map[b:2 a:1] } ``` Typical usage for value-only structures: ```go package main import ( "encoding/json" "fmt" "github.com/emirpasic/gods/lists/arraylist" ) func main() { list := arraylist.New() bytes := []byte(`["a","b"]`) err := json.Unmarshal(bytes, &list) // Same as "list.FromJSON(bytes)" if err != nil { fmt.Println(err) } fmt.Println(list) // ArrayList ["a","b"] } ``` ### Sort Sort is a general purpose sort function. Lists have an in-place _Sort()_ function and all containers can return their sorted elements via _containers.GetSortedValues()_ function. Internally these all use the _utils.Sort()_ method: ```go package main import "github.com/emirpasic/gods/utils" func main() { strings := []interface{}{} // [] strings = append(strings, "d") // ["d"] strings = append(strings, "a") // ["d","a"] strings = append(strings, "b") // ["d","a",b" strings = append(strings, "c") // ["d","a",b","c"] utils.Sort(strings, utils.StringComparator) // ["a","b","c","d"] } ``` ### Container Container specific operations: ```go // Returns sorted container''s elements with respect to the passed comparator. // Does not affect the ordering of elements within the container. func GetSortedValues(container Container, comparator utils.Comparator) []interface{} ``` Usage: ```go package main import ( "github.com/emirpasic/gods/lists/arraylist" "github.com/emirpasic/gods/utils" ) func main() { list := arraylist.New() list.Add(2, 1, 3) values := GetSortedValues(container, utils.StringComparator) // [1, 2, 3] } ``` ## Appendix ### Motivation Collections and data structures found in other languages: Java Collections, C++ Standard Template Library (STL) containers, Qt Containers, Ruby Enumerable etc. ### Goals **Fast algorithms**: - Based on decades of knowledge and experiences of other libraries mentioned above. **Memory efficient algorithms**: - Avoiding to consume memory by using optimal algorithms and data structures for the given set of problems, e.g. red-black tree in case of TreeMap to avoid keeping redundant sorted array of keys in memory. **Easy to use library**: - Well-structured library with minimalistic set of atomic operations from which more complex operations can be crafted. **Stable library**: - Only additions are permitted keeping the library backward compatible. **Solid documentation and examples**: - Learning by example. **Production ready**: - Used in production. **No dependencies**: - No external imports. There is often a tug of war between speed and memory when crafting algorithms. We choose to optimize for speed in most cases within reasonable limits on memory consumption. Thread safety is not a concern of this project, this should be handled at a higher level. ### Testing and Benchmarking This takes a while, so test within sub-packages: `go test -run=NO_TEST -bench . -benchmem -benchtime 1s ./...`
