{"id":21436760,"url":"https://github.com/modfin/henry","last_synced_at":"2025-07-14T14:33:22.372Z","repository":{"id":42473941,"uuid":"438575564","full_name":"modfin/henry","owner":"modfin","description":"Henry is a go library with generic helper functions in dealing with slices, maps and channels","archived":false,"fork":false,"pushed_at":"2024-04-24T15:22:45.000Z","size":112,"stargazers_count":50,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-20T19:52:21.562Z","etag":null,"topics":["functional","generics","go","go118","go2","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/modfin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-15T09:46:58.000Z","updated_at":"2024-04-24T15:22:49.000Z","dependencies_parsed_at":"2024-02-28T17:58:50.478Z","dependency_job_id":"396c9a71-fa9f-48eb-a9ad-cbe45fe3ec59","html_url":"https://github.com/modfin/henry","commit_stats":null,"previous_names":["modfin/go18exp","crholm/henry"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modfin%2Fhenry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modfin%2Fhenry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modfin%2Fhenry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/modfin%2Fhenry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/modfin","download_url":"https://codeload.github.com/modfin/henry/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225981808,"owners_count":17554923,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional","generics","go","go118","go2","golang"],"created_at":"2024-11-23T00:15:13.530Z","updated_at":"2024-11-23T00:15:14.210Z","avatar_url":"https://github.com/modfin.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Henry\n\n\u003e A collection of nice to have generic function and algorithms for slices, maps and channels\n\n[![GoDoc](https://godoc.org/github.com/modfin/henry?status.svg)](https://pkg.go.dev/github.com/modfin/henry)\n[![Go Report Card](https://goreportcard.com/badge/github.com/modfin/henry?cache)](https://goreportcard.com/report/github.com/modfin/henry)\n\nThis project came about in the experimentation with go1.18 and generics with helper functions for slices. It now also includes\nalgorithms and constructs for dealing with channels and maps as well\n\nIt is expected to that there might be a lot of these types of libraries floating around after the release of go1.18.\nThe go team did not include any of these fairly common constructs in this release but instead put some of them into \nthe exp package. There for the might be quite a bit of overlap in the coming releases with this and other packages.\n\nSome other work with similar concepts\n* https://github.com/golang/exp/tree/master/slices\n* https://github.com/golang/exp/tree/master/maps\n* https://github.com/samber/lo\n\n## Install\n\n```bash\ngo get github.com/modfin/henry/...\n```\n\n### Usage\n\nImport the part of henry you are interested of using\n\n```go\nimport (\n\"github.com/modfin/henry/chanz\"\n\"github.com/modfin/henry/mapz\"\n\"github.com/modfin/henry/slicez\"\n)\n```\n\nThen use the functions in the libraries such as\n\n```go \nupperPets := slicez.Map([]string{\"Dog\", \"Lizard\", \"Cat\"}, strings.ToUpper)) \n// []string{\"DOG\", \"LIZARD\", \"CAT\"}\n\n```\n\n\n#### Error handling\nIn go errors is made visible and is a core construct for sound code, so we can't simply ignore them.\nOne way of dealing with them is to wrap the result in a result type. This does have some implication in that \nearly returns might not be possible and might introduce some extra looping the check the result.\n\n**Example**\n```go \npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/modfin/henry/exp/result\"\n\t\"github.com/modfin/henry/slicez\"\n\t\"net/url\"\n)\n\nfunc parsUrls(stringUrls []string) ([]*url.URL, error) {\n    urls := slicez.Map(stringUrls, func(u string) result.Result[*url.URL] {\n        url, err := url.Parse(u)\n        return result.From(url, err)\n    })\n    return result.Unwrap(urls)\n}\n\nfunc main() {\n    stringUrls := []string{\n        \"https://example.com\",\n        \"https://github.com\",\n        \"bad\\n url\",\n    }\n    urls, err := parsUrls(stringUrls)\n    fmt.Println(\"URLs\", urls)\n    // URLs [https://example.com https://github.com]\n    \n    fmt.Println(\"Error\", err)\n    // Error parse \"bad\\n url\": net/url: invalid control character in URL\n}\n\n```\n\n## Content\n\nHenry contain tree main packages. `slicez`, `chanz` and `mapz`\n\n\nFunctions in `slicez`\n* Clone\n* Compact\n* CompactFunc\n* Compare\n* CompareFunc\n* Complement\n* ComplementBy\n* Concat\n* Contains\n* ContainsFunc\n* Cut\n* CutFunc\n* Difference\n* DifferenceBy\n* Drop\n* DropRight\n* DropRightWhile\n* DropWhile\n* Each\n* Equal\n* EqualFunc\n* Every\n* EveryFunc\n* Filter\n* Find\n* FindLast\n* FlatMap\n* Flatten\n* Fold\n* FoldRight\n* GroupBy\n* Head\n* Index\n* IndexFunc\n* Intersection\n* IntersectionBy\n* Join\n* KeyBy\n* Last\n* LastIndex\n* LastIndexFunc\n* Map\n* Max\n* Min\n* None\n* NoneFunc\n* Nth\n* Partition\n* Reject\n* Reverse\n* Sample\n* Search\n* Shuffle\n* Some\n* SomeFunc\n* Sort\n* SortFunc\n* Tail\n* Take\n* TakeRight\n* TakeRightWhile\n* TakeWhile\n* Union\n* UnionBy\n* Uniq\n* UniqBy\n* Unzip\n* Unzip2\n* Zip\n* Zip2\n\n\nFunctions in `mapz`\n* Clear\n* Clone\n* Copy\n* DeleteFunc\n* DeleteValue\n* Equal\n* EqualFunc\n* Keys\n* Merge\n* Remap\n* Values\n\nFunctions in `chanz`\n\n* Collect\n* CollectUntil\n* Compact\n* Compact1\n* CompactN\n* CompactUntil\n* Concat\n* Concat1\n* ConcatN\n* ConcatUntil\n* Drop\n* Drop1\n* DropAll\n* DropN\n* DropUntil\n* DropWhile\n* DropWhile1\n* DropWhileN\n* DropWhileUntil\n* EveryDone\n* FanOut\n* FanOut1\n* FanOutN\n* FanOutUntil\n* Filter\n* Filter1\n* FilterN\n* FilterUntil\n* Flatten\n* Flatten1\n* FlattenN\n* FlattenUntil\n* Generate\n* Generate1\n* GenerateN\n* GenerateUntil\n* Map\n* Map1\n* MapN\n* MapUntil\n* Merge\n* Merge1\n* MergeN\n* MergeUntil\n* Partition\n* Partition1\n* PartitionN\n* PartitionUntil\n* Peek\n* Peek1\n* PeekN\n* PeekUntil\n* Readers\n* SomeDone\n* Take\n* Take1\n* TakeN\n* TakeUntil\n* TakeWhile\n* TakeWhile1\n* TakeWhileN\n* TakeWhileUntil\n* Unzip\n* Unzip1\n* UnzipN\n* UnzipUntil\n* Writers\n* Zip\n* Zip1\n* ZipN\n* ZipUntil\n\n\n\n## Slicez\n\nThe `slicez` package contains generic utility functions and algorithms for slices\n\n### Clone\n\nProduces a copy of a given slice\n\n```go \ns := []int{1,2,3}\nclone := slicez.Clone[int](s)\n// []int{1,2,3}\n```\n\n### Compact\n\nRemoves consecutive duplicates from a slice\n\n```go \ns := []int{1, 1, 2, 3, 3}\nslicez.Compact[int](s)\n// []int{1,2,3}\n```\n\n### CompactFunc\n\nRemoves consecutive duplicates from a slice using a function for determine equality\n\n```go \ns := []rune(\"Alot    of  white  spaces\")\nslicez.CompactFunc[rune](s, func(a, b rune) {\n     return a == ' ' \u0026\u0026 a == b\n})\n// \"Alot of white spaces\"\n```\n\n### Compare\n\nCompares two slices for equality\n\n```go\ns1 := []int{1, 2, 3}\ns2 := []int{1, 2, 3}\nslicez.Compare[int](s1, s2)\n// 0\n```\n\n### CompareFunc\n\nCompares two slices for equality with supplied func\n\n```go\ns1 := []int{1, 2, 3}\ns2 := []int{4, 5, 6}\nslicez.CompareFunc[int](s1, s2, func (a, b int) int{\nreturn a%4 - b%4\n})\n// 0\n```\n\n### Complement\n\nReturns the complement of two slices\n\n```go \na := []int{1, 2, 3}\nb := []int{3, 2, 5, 5, 6, 1}\nslicez.Complement[int](a, b)\n// []int{5, 6}\n```\n\n### ComplementBy\n\n### Concat\n\nConcatenates slices into a new slice\n\n```go \na := []int{1, 2, 3}\nb := []int{4, 5, 6}\nb := []int{7, 8, 9}\nslicez.Concat[int](a, b, c)\n// []int{1, 2, 3, 4, 5, 6, 7, 8, 9}\n```\n\n### Contains\n\nReturn true if an element is present in the slice\n\n```go \nslicez.Contains[int]([]int{1, 2, 3, 4, 5}, 3)\n// true\n```\n\n### ContainsFunc\n\nReturns true if the function returns true.\n\n```go \nslicez.ContainsFunc[int]([]int{4, 5, 6, 7}, func(i int){ \n    return i % 4 == 3\n})\n// true\n```\n\n### Cut\n\nCuts a slice into two parts\n\n```go \nslicez.Cut[int]([]int{1,2,3,4,5}, 3)\n// []int{1,2}, []int{4,5}, true\n```\n\n### CutFunc\n\nCuts a slice into two parts\n\n```go \nslicez.CutFunc[int]([]int{1,2,3,4,5}, func(i int){ return i == 3}) \n// []int{1,2}, []int{4,5}, true\n```\n\n### Difference\n\nReturns the difference between slices\n\n```go \na := []int{1,2,3}\nb := []int{2,3,4}\nc := []int{2,3,5}\nslicez.Difference[int](a, b, c) \n// []int{1,4,5}\n```\n\n### DifferenceBy\n\n### Drop\n\nDrops the first N elements\n\n```go\nslicez.Drop[int]([]int{1, 2, 3, 4, 5}, 2)\n// []int{3,4,5}\n```\n\n### DropRight\n\nDrops the last N elements\n\n```go\nslicez.DropRight[int]([]int{1, 2, 3, 4, 5}, 2)\n// []int{1,2,3}\n```\n\n### DropWhile\n\nDrops elements from the left until function returns false\n\n```go\nslicez.DropWhile[int]([]int{1, 2, 3, 4, 5}, func (i int) {return i \u003c 3})\n// []int{3,4,5}\n```\n\n### DropRightWhile\n\nDrops elements from the right until function returns false\n\n```go\nslicez.DropRightWhile[int]([]int{1, 2, 3, 4, 5}, func (i int) {return i \u003e 3})\n// []int{1,2,3}\n```\n\n### Each\n\nApplies a function to each element of a slice\n\n```go\nslicez.Each[int]([]int{1, 2, 3}, func (i int) { fmt.Print(i) })\n// 123\n```\n\n### Equal\n\nReturns true if two slices are identical\n\n```go\ns1 := []int{1, 2, 3}\ns2 := []int{1, 2, 3}\nslicez.Equal[int](s1, s2)\n// true\n```\n\n### EqualFunc\n\nReturns true if two slices are identical, given an equality function\n\n```go\ns1 := []int{1, 2, 3}\ns2 := []int{4, 5, 6}\nslicez.EqualFunc[int, int](s1, s2, func (a, b int) int{\nreturn a%4 - b%4\n})\n// true\n```\n\n### Every\n\nReturns true if every element matches the given value\n\n```go\ns1 := []int{1, 1, 1}\nslicez.Every[int](s1, 1)\n// true\n```\n\n### EveryFunc\n\n### Every\n\nReturns true if every element matches the given value using the equality function\n\n```go\ns1 := []int{0, 3, 6}\nslicez.EveryFunc[int](s1, func (i int) { return i % 3 == 0})\n// true\n```\n\n### Filter\n\nFilters a slice to contain things we are looking for\n\n```go\ns1 := []int{1, 2, 3, 4}\nslicez.Filter[int](s1, func (i int) { return i % 2 == 0})\n// []int{2,4}\n```\n\n### Find\n\nFind returns the first instance of an object where the function returns true\n\n```go\ns1 := []int{1, 2, 3, 4, 5,6, 7}\nslicez.Find[int](s1, func (i int) { return i % 3 == 0})\n// 3\n```\n\n### FindLast\n\nFindLast returns the last instance of an object where the function returns true\n\n```go\ns1 := []int{1, 2, 3, 4, 5,6, 7}\nslicez.FindLast[int](s1, func (i int) { return i % 3 == 0})\n// 6\n```\n\n### FlatMap\n\nTakes a slice, expands every element into a slice and flattens it to a single slice\n\n```go \ns := []string{\"a b c\", \"d e f\"}\n\nslicez.FlatMap(s, func(e string) []string {\n    return strings.Split(e, \" \")\n})\n// []string{\"a\",\"b\",\"c\",\"d\",\"e\",\"f\"}\n```\n\n### Flatten\n\nFlattens a nested slice\n\n```go \ns := [][]string{{\"a\", \"b\"}, {\"c\",\"d\"}}\nslicez.Flatten(s)\n// []string{\"a\",\"b\",\"c\",\"d\"}\n```\n\n### Fold\n\nFolds a slice into a value from the left (aka reduce)\n\n```go \ns := []string{\"a\", \"b\", \"c\",\"d\"}\nslicez.Fold[string, string](s, func(acc string, str string) string { return acc + str}, \"\u003e\")\n// \"\u003eabcd\"\n```\n\n### FoldRight\n\nFolds a slice into a value from the right (aka reduce)\n\n```go \ns := []string{\"a\", \"b\", \"c\",\"d\"}\nslicez.FoldRight[string, string](s, func(acc string, str string) string { return acc + str}, \"\u003e\")\n// \"\u003edcba\"\n```\n\n### GroupBy\n\nGroups elements in a slice into a map\n\n```go \ns = []int{0,1,2,3}\nslicez.GroupBy(s, func(e int) int {return i % 2})\n// map[int][]int{0: [0,2], 1:[1,2]}\n```\n\n### Head\n\nReturns the first element of a slice if present\n\n```go \nslicez.Head([]int{1,2,3})\n// 1, nil\n```\n\n### Index\n\nReturns the index of the first occurrence of an element\n\n```go  \nslicez.Index([]int{1,2,3}, 2)\n// 1\n```\n\n### IndexFunc\n\nReturns the index of the first occurrence of an element using a function\n\n```go  \nslicez.IndexFunc([]int{1,2,3}, func(i int) bool {i % 2 == 1})\n// 0\n```\n\n### Intersection\n\nReturns the intersection of slices\n\n```go \na := []int{1,2,3,4}\nb := []int{3,4,5,6}\nc := []int{3,4,8,9}\nslicez.Intersection(a,b,c)\n// []int{3,4}\n```\n\n### IntersectionBy\n\n### Intersection\n\nReturns the intersection of slices\n\n```go \na := []int{0,1}\nb := []int{4,2}\nc := []int{8,3}\nslicez.IntersectionBy(func(i int) int {\n    return i % 4\n} a,b,c)\n// []int{0,4,8}\n```\n\n### Join\n\nJoining a 2d slice into 1d slice using a glue\n\n```go \ns = [][]string{{\"hello\", \" \", \"world\"}, {\"or\", \" \", \"something\"}}\nslicez.Join(s, []string{\" \"})\n// []string{\"hello\", \" \", \"world\", \" \", \"or\", s\" \", \"something\"}\n```\n\n### KeyBy\n\nReturns a map with the slice elements in it, using the by function to determine key\n\n```go \ns = []int{1,2,3,4}\nslicez.KeyBy(s, func(i int) int { return i % 3 })\n// map[int]int{0: 3, 1: 1, 2: 2}\n```\n\n### Last\n\nReturns the last element in a slice, or an error if len(s) == 0\n\n```go \nslicez.Last([]int{1,2,3})\n// 3, nil\n```\n\n### LastIndex\n\nFinds the last index of a needle, or -1 if not present\n\n```go \nslicez.LastIndex([]int{1,1,2,1,3}, 1)\n// 3\n```\n\n### LastIndexFunc\n\n### LastIndex\n\nFinds the last index of a func needle, or -1 if not present\n\n```go \nslicez.LastIndex([]int{1,2,3,4,5}, func(i int) bool { return i % 3 == 1})\n// 2\n```\n\n### Map\n\nMap values in a slice producing a new one\n\n```go \ns := []int{1,2,3}\nslicez.Map(s, func(i int) string { return fmt.Sprint(i)})\n// []string{\"1\",\"2\",\"3\"}\n```\n\n### Max\n\nReturns the maximum value of a slice\n\n```go \ns := []int{1,2,5,4}\nslicez.Max(s...)\n// 5\n```\n\n### Min\n\nReturns the minimum value of a slice\n\n```go \ns := []int{1,2,5,0, 4}\nslicez.Min(s...)\n// 0\n```\n\n### None\n\nReturns true if no element match the needle\n\n```go \ns := []int{1,2,3}\nslicez.None(s, 0)\n// true\n```\n\n### NoneFunc\n\nReturns true if no element returns true from the function\n\n```go \ns := []int{1,2,3}\nslicez.NoneFunc(s, func(i int) bool { return i \u003c 1 })\n// true\n```\n\n### Nth\n\nReturns the N:th element in a slice, zero value if empty and regards the slice as a modulo group\n\n```go \ns := []int{1,2,3}\nslicez.Nth(s, 1)\n// 2\nslicez.Nth(s, 3)\n// 1\nslicez.Nth(s, -1)\n// 3\n```\n\n### Partition\n\nReturns two slices which represents the partitions\n\n```go \ns := []int{1,2,3,4}\nslicez.Partition(s, func(i int) bool { return i % 2 == 0})\n// []int{2,4}, []int{1,3}\n```\n\n### Reject\n\nReject is the complement to Filter and excludes items\n\n```go \ns := []int{1,2,3,4}\nslicez.Reject(s, func(i int) bool { return i % 2 == 0})\n// []int{1,3}\n```\n\n### Reverse\n\nReverses a slice\n\n```go \ns := []int{1,2,3}\nslicez.Reverse(s)\n//[]int{3,2,1}\n```\n\n### Sample\n\nReturns a random sample of size N from the slice\n\n```go \ns := []int{1,2,3,4,5,6,7,8}\nslicez.Sample(s, 2)\n//[]int{8,3}\n```\n\n### Search\n\n### Shuffle\n\nReturns a shuffled version of the slice\n\n```go \ns := []int{1,2,3,4,5}\nslicez.Shuffle(s)\n//[]int{3,1,4,5,3}\n```\n\n### Some\n\nReturns true there exist an element in the slice that is equal to the needle, an alias for Contains\n\n```go \ns := []int{1,2,3,4,5}\nslicez.Some(s, 4)\n//true\n```\n\n### SomeFunc\n\nReturns true if there is an element in the slice for which the predicate function returns true\n\n```go \ns := []int{1,2,3,4,5}\nslicez.SomeFunc(s, func(i int) bool { return i \u003e 4})\n//true\n```\n\n### Sort\n\nSorts a slice\n\n```go \ns := []int{3,2,1}\nslicez.Sort(s)\n//[]int{1,2,3}\n```\n\n### SortFunc\n\nSorts a slice with a comparator\n\n```go \ns := []int{1,2,3}\nslicez.SortFunc(s, func(a, b int) bool { return b \u003c a })\n//[]int{3,2,1}\n```\n\n### Tail\n\nReturns the tail of a slice\n\n```go \ns := []int{1,2,3}\nslicez.Tail(s)\n// []int{2,3}\n```\n\n### Take\n\nReturns the N first element of a slice\n\n```go \ns := []int{1,2,3,4}\nslicez.Take(s, 2)\n// []int{1,2}\n```\n\n### TakeRight\n\nReturns the N last element of a slice\n\n```go \ns := []int{1,2,3,4}\nslicez.TakeRight(s, 2)\n// []int{3, 4}\n```\n\n### TakeWhile\n\nReturns the first element of a slice that as long as function returns t\n\n```go \ns := []int{1,2,3,4}\nslicez.TakeRight(s, func(i int) bool { return i \u003c 3})\n// []int{1, 2}\n```\n\n### TakeRightWhile\n\nReturns the last element of a slice that as long as function returns t\n\n```go \ns := []int{1,2,3,4}\nslicez.TakeWhileRight(s, func(i int) bool { return i \u003e 2})\n// []int{3, 4}\n```\n\n### Union\n\nReturs the union of a slices\n\n```go \na := []int{1,2,3}\nb := []int{3,4,5}\nslicez.Union(a, b)\n// []int{1,2,3,4,5}\n```\n\n### UnionBy\n\nReturs the union of a slices using a function for equality\n\n```go \na := []int{1,5}\nb := []int{2,4}\nslicez.UnionBy(func(i int) bool { return i % 2 == 0 } a, b)\n// []int{1,2}\n```\n\n### Uniq\n\nReturns a slice of uniq elements\n\n```go \na := []int{1,2,3,1,3,4}\nslicez.Uniq(a)\n// []int{1,2,3,4}\n```\n\n### UniqBy\n\nReturns a slice of uniq elements, where equality is determined through the function\n\n```go \na := []int{1,2,3,1,3,4}\nslicez.UniqBy(a, func(i int) bool { return i % 2 == 0 })\n// []int{1,2}\n```\n\n### Unzip\n\nTakes a slice and unzips it into two slices\n\n```go \ns := []int{-1,2}\nslicez.Unzip(s, func(i int) (bool, int){\n    return i \u003e 0, int(Math.Abs(i))\n})\n// []bool{false, true}, []int{1,2}\n```\n\n### Unzip2\n\nTakes a slice and unzips it into three slices\n\n```go \ns := []int{-2,-1,2}\nslicez.Unzip(s, func(i int) (bool, bool, int){\n    return i \u003e 0, i % 2 == 0, int(Math.Abs(i))\n})\n// []bool{false, false, true}, []bool{true, false, true}, []int{2, 1,2}\n```\n\n### Zip\n\nTakes 2 slices and zips them into one slice\n\n```go \na := []int{1,2,3}\nb := []string{\"a\",\"b\",\"c\"}\nslicez.Zip(a,b, func(i int, s string) string {\n    return fmt.Sprint(i, s)\n})\n// []string{\"1a\", \"2b\", \"3c\"}\n```\n\n### Zip2\n\nTakes 3 slices and zips them into one slice\n\n```go \na := []int{1,2,3}\nb := []string{\"a\",\"b\",\"c\"}\nb := []bool{true, false, true}\nslicez.Zip(a, b, c, func(i int, s string, b bool) string {\n    return fmt.Sprint(b, i, s)\n})\n// []string{\"true1a\", \"false2b\", \"true3c\"}\n```\n\n## Mapz\nThe `mapz` package contains generic utility functions and algorithms for maps\n\n### Clear\nDeletes every entry in a map\n\n```go \nm := map[int]int{1:1, 2:2}\nmapz.Clear(m)\n// map[int]int{}\n```\n\n### Clone\nCreates a clone of a map\n```go \nm := map[int]int{1:1, 2:2}\nmapz.Clone(m)\n// map[int]int{1:1, 2:2}\n```\n\n### Copy\nCopies one map into another\n\n```go\nsrc := map[int]int{1:1, 2:2}\ndst := map[int]int{1:0, 3:3}\nmapz.Copy(dst, src)\n//  map[int]int{1:1, 2:2, 3:3}\n```\n\n### DeleteFunc\nWill remove all entries from a map where the del function returns true\n\n```go\nm := map[int]int{1:1, 2:2, 3:3}\nmapz.DeleteFunc(m, func(k, v int) bool { return k == 2 })\n//  map[int]int{1:1, 3:3}\n```\n\n### DeleteValue\nDeletes a value and the associated key from a map\n```go\nm := map[int]int{1:1, 2:800, 3:3}\nmapz.DeleteValue(m, 800)\n//  map[int]int{1:1, 3:3}\n```\n\n### Equal\nReturns true if a map i equal\n\n```go \nm1 := map[int]int{1:1, 3:3}\nm2 := map[int]int{1:1, 3:3}\nmapz.Equal(m1, m2)\n// true\n```\n\n\n### EqualFunc\nReturns true if a map i equal using the equality function to test it\n```go \nm1 := map[int]int{1:1, 3:3}\nm2 := map[int]int{1:1, 3:6}\nmapz.EqualFunc(m1, m2, func(a, b int) bool {return a % 3 == b % 3})\n// true\n```\n\n### Keys\nReturns a slice of all keys in the map\n\n```go \nm := map[int]int{1:1, 3:3}\nmapz.Keys(m)\n// []int{1,3}\n```\n\n\n### Merge\nMerges multiple maps into one map\n```go\nm1 := map[int]int{1:1, 3:3, 4:800}\nm2 := map[int]int{2:2, 4:4}\nmapz.Merge(m1, m2)\n// map[int]int{1:1, 2:2, 3:3, 4:4}\n```\n\n### Remap\nRemaps a map in terms of its keys and values\n\n```go \nm := map[int]int{2:2, 4:4}\nmapz.Remap(m, func(k, v int) (k2, v2 string){\n    return fmt.Sprint(k), fmt.Sprint(v*2)\n})\n// map[string]string{\"2\":\"4\", \"4\":\"8\"}\n```\n\n### Values\nReturns a slice of all values in the map\n```go \nm := map[int]int{2:6, 4:12}\nmapz.Values(m)\n// []int{6,12}\n```\n\n\n## Chanz\n\nThe `chanz` package contains generic utility functions and algorithms for channels\n\n### SomeDone\nTakes N channels as input and returns one channel. If any of the input channels is closed, the output channel is closed. This \nis used for control structure.\n\n```go \ndone1 := make(chan, interface{})\ndone2 := make(chan, interface{})\n\ndone := chanz.SomeDone(done1, done2)\n\ngo func(){\n   time.Sleep(time.Second)\n    close(done1)\n    time.Sleep(time.Second)\n    close(done2)\n}\n\n\u003c- done // will read in 1 secound\n```\n\n\n\n### EveryDone\nTakes N channels as input and returns one channel. When all input channels is closed, the output channel will be closed.  This\nis used for control structure.\n\n```go \ndone1 := make(chan, interface{})\ndone2 := make(chan, interface{})\n\ndone := chanz.SomeDone(done1, done2)\n\ngo func(){\n    time.Sleep(time.Second)\n    close(done1)\n    time.Sleep(time.Second)\n    close(done2)\n}\n\n\u003c- done // will read in 2 seconds\n```\n\n\n### Collect, CollectUntil\nWill collect all read items into a slice and return it\n\n```go \nin := chanz.Generate(1,2,3,4,5)\nchanz.Collect(in)\n// []int{1,2,3,4,5}\n```\n\n\n### Compact, Compact1, CompactN, CompactUntil\nWill remove consecutive duplicates from the channel\n\n```go \nin := chanz.Generate(1,1,3,2,2,5,1)\nw := chanz.Compact(in)\nchanz.Collect(w)\n// []int{1,3,2,5,1}\n```\n\n\n\n\n### Concat, Concat1, ConcatN, ConcatUntil\nWill concatenate channels\n\n```go \nin1 := chanz.Generate(1,2,3)\nin2 := chanz.Generate(4,5,6)\nw := chanz.Concat(in1, in2)\nchanz.Collect(w)\n// []int{1,2,3,4,5,6}\n```\n\n### Drop, Drop1, DropN, DropUntil\nDrops the first N entries of the channel\n\n```go \nin := chanz.Generate(1,2,3,4,5,6)\nw := chanz.Drop(in, 2)\nchanz.Collect(w)\n// []int{3, 4, 5, 6}\n```\n\n\n### DropWhile, DropWhile1, DropWhileN, DropWhileUntil\nDrops the first entries of the channel until function returns true\n\n```go \nin := chanz.Generate(1,2,3,4,5,6,1)\nw := chanz.DropWhile(in, func(i int) bool { return i \u003c 3})\nchanz.Collect(w)\n// []int{3, 4, 5, 6, 1}\n```\n\n\n### DropAll\nDrops all elements until closed\n\n```go \nin := chanz.Generate(1,2,3,4,5,6)\nw := chanz.DropAll(in, false)\nchanz.Collect(w)\n// []int{}\n```\n\n### DropBuffer\nDrops all elements that is buffered in the chan\n\n```go \nin :=  chanz.GenerateWith[int](chanz.Buffer(2))(1,2,3,4,5,6)\nchanz.DropBuffer(in, false)\nchanz.Collect(in)\n// []int{3,4,5,6}\n```\n\n\n### TakeBuffer\nTake all elements that is buffered in the chan\n\n```go \nin := chanz.GenerateWith[int](chanz.Buffer(2))(1,2,3,4,5,6)\nr := chanz.TakeBuffer(in)\n// []int{1,2}\nc := chanz.Collect(w)\n// []int{3,4,5,6}\n```\n\n\n\n### FanOut\nTakes an input channel and fans it out to multiple output channels\n```go\nin := chanz.Generate(1,2,3,4,5,6)\nchans := chanz.FanOut(in, 2)\ngo chanz.Collect(chans[0])\nchanz.Collect(chans[1])\n// []int{1,2,3,4,5,6}\n// []int{1,2,3,4,5,6}\n```\n\n### Filter\nFilters the items read onto the output chan\n\n```go \nin := chanz.Generate(1,2,3,4,5,6)\neven := chanz.Filter(in, func(i int) bool { return i % 2 == 0})\nchanz.Collect(even)\n// []int{2,4,6}\n```\n\n### Flatten\nFlattens a channel that produces slices\n\n```go \nin := chanz.Generate([]int{1,2,3}, []int{4,5,6})\nw := chanz.Flatten(in)\nchanz.Collect(w)\n// []int{1,2,3,4,5,6}\n```\n\n\n\n### Generate\nTakes elements, creates a channel and writes the elements to it\n```go\nw := chanz.Generate(1,2,3,4)\nchanz.Collect(w)\n// []int{1,2,3,4}\n```\n\n\n### Map\nMaps element from one channel to another\n\n```go \nin := chanz.Generate(1,2,3,4)\nw := chanz.Map(in, func(i int) string { return fmt.Sprint(i) })\nchanz.Collect(w)\n// []string{\"1\",\"2\",\"3\",\"4\"}\n```\n\n\n### Merge\nMerge will take N chans and merge them onto one channel (in a non-particular order)\n\n```go \nin1 := chanz.Generate(1,2,3)\nin2 := chanz.Generate(4,5,6)\nw := chanz.Merge(in1, in2)\nchanz.Collect(w)\n// []int{4,1,5,6,2,3}\n```\n\n\n\n### Partition\nPartition a channel into to two channels\n```go \nin := chanz.Generate(1,2,3,4,5,6)\neven, odd := chanz.Partition(in, func(i int) bool { return i % 2 == 0})\ngo chanz.Collect(even)\nchanz.Collect(odd)\n// []int{2,4,6}\n// []int{1,3,5}\n```\n\n\n### Peek\nWill produce a channel that runs a function for each item\n\n```go \nin := chanz.Generate(1,2,3,4,5,6)\nin := chanz.Peek(in, func(i int){ fmt.Print(i)})\nchanz.Collect(in)\n// 123456\n// []int{1,2,3,4,5,6}\n```\n\n\n### Take\nWill take the first N items from the channel\n\n```go \nin := chanz.Generate(1,2,3,4,5,6)\nw := chanz.Take(in, 2)\nchanz.Collect(w)\n// []int{1,2}\n```\n\n### TakeWhile\n\nWill take the first items from the channel until the predicate function returns false\n\n```go \nin := chanz.Generate(1,2,3,4,5,6)\nw := chanz.TakeWhile(in, func(i int) bool{ return i \u003c 3})\nchanz.Collect(w)\n// []int{1,2}\n```\n\n### Unzip\nTakes one chan and unzips it into two\n\n```go \nin := chanz.Generate(-2, -1, 1, 2)\npossitive, value := chanz.Unzip(in, func(i int) (bool, int) {\n    return i \u003e 0, Math.Abs(i)\n})\ngo chanz.Collect(possitive)\nchanz.Collect(value)\n// []bool{false, false, true, true}\n// []int{2,1,1,2}\n```\n\n### Zip\nTakes two channels and zips them into one channel \n\n```go \nin1 := chanz.Generate(1,2,3)\nin2 := chanz.Generate(\"a\",\"b\",\"c\")\nx := chanz.Unzip(in1, in2, func(i int, s string) string {\n    return fmt.Sprint(i,s)\n})\nchanz.Collect(w)\n// []string{\"1a\", \"2b\", \"3c\"}\n```\n\n\n### Readers\nTakes a slice of channels and returns a slice casted to read channels\n\n### Writers\nTakes a slice of channels and returns a slice casted to write channels\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmodfin%2Fhenry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmodfin%2Fhenry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmodfin%2Fhenry/lists"}