├── .chglog
├── CHANGELOG.tpl.md
└── config.yml
├── .github
└── workflows
│ └── go.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── add_test.go
├── bool.go
├── bool_test.go
├── clear_test.go
├── contains_test.go
├── deduplicate_test.go
├── float32.go
├── float32_test.go
├── float64.go
├── float64_test.go
├── go.mod
├── int.go
├── int16.go
├── int16_test.go
├── int32.go
├── int32_test.go
├── int64.go
├── int64_test.go
├── int8.go
├── int8_test.go
├── int_test.go
├── interface.go
├── interface_test.go
├── join_test.go
├── length_test.go
├── logo.png
├── scripts
├── generate.go
└── slicer.template
├── string.go
├── string_test.go
├── uint.go
├── uint16.go
├── uint16_test.go
├── uint32.go
├── uint32_test.go
├── uint64.go
├── uint64_test.go
├── uint8.go
├── uint8_test.go
└── uint_test.go
/.chglog/CHANGELOG.tpl.md:
--------------------------------------------------------------------------------
1 | {{ if .Versions -}}
2 |
3 | ## [Unreleased]
4 |
5 | {{ if .Unreleased.CommitGroups -}}
6 | {{ range .Unreleased.CommitGroups -}}
7 | ### {{ .Title }}
8 | {{ range .Commits -}}
9 | - {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
10 | {{ end }}
11 | {{ end -}}
12 | {{ end -}}
13 | {{ end -}}
14 |
15 | {{ range .Versions }}
16 |
17 | ## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
18 | {{ range .CommitGroups -}}
19 | ### {{ .Title }}
20 | {{ range .Commits -}}
21 | - {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
22 | {{ end }}
23 | {{ end -}}
24 |
25 | {{- if .NoteGroups -}}
26 | {{ range .NoteGroups -}}
27 | ### {{ .Title }}
28 | {{ range .Notes }}
29 | {{ .Body }}
30 | {{ end }}
31 | {{ end -}}
32 | {{ end -}}
33 | {{ end -}}
34 |
35 | {{- if .Versions }}
36 | [Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
37 | {{ range .Versions -}}
38 | {{ if .Tag.Previous -}}
39 | [{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
40 | {{ end -}}
41 | {{ end -}}
42 | {{ end -}}
--------------------------------------------------------------------------------
/.chglog/config.yml:
--------------------------------------------------------------------------------
1 | style: github
2 | template: CHANGELOG.tpl.md
3 | info:
4 | title: CHANGELOG
5 | repository_url: https://github.com/leaanthony/slicer
6 | options:
7 | commits:
8 | # filters:
9 | # Type:
10 | # - feat
11 | # - fix
12 | # - perf
13 | # - refactor
14 | commit_groups:
15 | # title_maps:
16 | # feat: Features
17 | # fix: Bug Fixes
18 | # perf: Performance Improvements
19 | # refactor: Code Refactoring
20 | header:
21 | pattern: "^(\\w*)\\:\\s(.*)$"
22 | pattern_maps:
23 | - Type
24 | - Subject
25 | notes:
26 | keywords:
27 | - BREAKING CHANGE
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: Go
2 | on: [push]
3 | jobs:
4 |
5 | build:
6 | name: Build
7 | runs-on: ubuntu-latest
8 | steps:
9 |
10 | - name: Set up Go 1.13
11 | uses: actions/setup-go@v1
12 | with:
13 | go-version: 1.13
14 | id: go
15 |
16 | - name: Check out code into the Go module directory
17 | uses: actions/checkout@v1
18 |
19 | - name: Get dependencies
20 | run: |
21 | go get -v -t -d ./...
22 | if [ -f Gopkg.toml ]; then
23 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
24 | dep ensure
25 | fi
26 |
27 | - name: Build
28 | run: go build -v .
29 |
30 | - name: Test
31 | run: go test -race -coverprofile=coverage.txt -covermode=atomic
32 |
33 | - name: CodeCov
34 | uses: codecov/codecov-action@v1
35 | with:
36 | token: ${{ secrets.CODECOV_TOKEN }} #required
37 | file: ./coverage.txt
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, build with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 | coverage.txt
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## [Unreleased]
3 |
4 |
5 |
6 | ## [v1.3.1] - 2019-03-03
7 | ### Fix
8 | - Fix Float tests
9 |
10 |
11 |
12 | ## [v1.3.0] - 2019-03-03
13 | ### Feat
14 | - Add optional slice as part of construction
15 |
16 |
17 |
18 | ## [v1.2.0] - 2019-02-26
19 | ### Chore
20 | - add changelog
21 |
22 | ### Feat
23 | - Add Slicer.Each()
24 |
25 |
26 |
27 | ## [v1.1.0] - 2019-02-26
28 | ### Feat
29 | - Added Filter
30 |
31 |
32 |
33 | ## v1.0.0 - 2019-01-13
34 |
35 | [Unreleased]: https://github.com/leaanthony/slicer/compare/v1.3.1...HEAD
36 | [v1.3.1]: https://github.com/leaanthony/slicer/compare/v1.3.0...v1.3.1
37 | [v1.3.0]: https://github.com/leaanthony/slicer/compare/v1.2.0...v1.3.0
38 | [v1.2.0]: https://github.com/leaanthony/slicer/compare/v1.1.0...v1.2.0
39 | [v1.1.0]: https://github.com/leaanthony/slicer/compare/v1.0.0...v1.1.0
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Lea Anthony
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 | Utility class for handling slices.
5 |
6 |
7 |
8 | [](https://goreportcard.com/report/github.com/leaanthony/slicer) [](http://godoc.org/github.com/leaanthony/slicer) [](https://www.codefactor.io/repository/github/leaanthony/slicer) [](https://codecov.io/gh/leaanthony/slicer) [](https://github.com/avelino/awesome-go)
9 |
10 |
11 |
12 |
13 |
14 | ## Install
15 |
16 | `go get -u github.com/leaanthony/slicer`
17 |
18 | ## Quick Start
19 |
20 | ```
21 | import "github.com/leaanthony/slicer"
22 |
23 | func test() {
24 | s := slicer.String()
25 | s.Add("one")
26 | s.Add("two")
27 | s.AddSlice([]string{"three","four"})
28 | fmt.Printf("My slice = %+v\n", s.AsSlice())
29 |
30 | t := slicer.String()
31 | t.Add("zero")
32 | t.AddSlicer(s)
33 | fmt.Printf("My slice = %+v\n", t.AsSlice())
34 | }
35 | ```
36 |
37 | ## Available slicers
38 |
39 | - Int
40 | - Int8
41 | - Int16
42 | - Int32
43 | - Int64
44 | - UInt
45 | - UInt8
46 | - UInt16
47 | - UInt32
48 | - UInt64
49 | - Float32
50 | - Float64
51 | - String
52 | - Bool
53 | - Interface
54 |
55 | ## API
56 |
57 | ### Construction
58 |
59 | Create new Slicers by calling one of the following functions:
60 | - Int()
61 | - Int8()
62 | - Int16()
63 | - Int32()
64 | - Int64()
65 | - Float32()
66 | - Float64()
67 | - String()
68 | - Bool()
69 | - Interface()
70 |
71 | ```
72 | s := slicer.String()
73 | ```
74 |
75 | If you wish to convert an existing slice to a Slicer, you may pass it in during creation:
76 |
77 | ```
78 | values := []string{"one", "two", "three"}
79 | s := slicer.String(values)
80 | ```
81 |
82 | ### Add
83 |
84 | Adds a value to the slice.
85 |
86 | ```
87 | values := []string{"one", "two", "three"}
88 | s := slicer.String(values)
89 | s.Add("four")
90 | ```
91 |
92 | ### AddUnique
93 |
94 | Adds a value to the slice if it doesn't already contain it.
95 |
96 | ```
97 | values := []string{"one", "two", "three", "one", "two", "three"}
98 | s := slicer.String(values)
99 | result := s.Join(",")
100 | // result is "one,two,three"
101 | ```
102 | ### AddSlice
103 |
104 | Adds an existing slice of values to a slicer
105 |
106 | ```
107 | s := slicer.String([]string{"one"})
108 | s.AddSlice([]string{"two"})
109 | ```
110 |
111 | ### AsSlice
112 |
113 | Returns a regular slice from the slicer.
114 |
115 | ```
116 | s := slicer.String([]string{"one"})
117 | for _, value := range s.AsSlice() {
118 | ...
119 | }
120 | ```
121 |
122 | ### AddSlicer
123 |
124 | Adds an existing slicer of values to another slicer
125 |
126 | ```
127 | a := slicer.String([]string{"one"})
128 | b := slicer.String([]string{"two"})
129 | a.AddSlicer(b)
130 | ```
131 |
132 | ### Filter
133 |
134 | Filter the values of a slicer based on the result of calling the given function with each value of the slice. If it returns true, the value is added to the result.
135 |
136 | ```
137 | a := slicer.Int([]int{1,5,7,9,6,3,1,9,1})
138 | result := a.Filter(func(v int) bool {
139 | return v > 5
140 | })
141 | // result is []int{7,9,9}
142 |
143 | ```
144 |
145 | ### Each
146 |
147 | Each iterates over all the values of a slicer, passing them in as paramter to a function
148 |
149 | ```
150 | a := slicer.Int([]int{1,5,7,9,6,3,1,9,1})
151 | result := 0
152 | a.Each(func(v int) {
153 | result += v
154 | })
155 | // result is 42
156 | ```
157 |
158 | ### Contains
159 |
160 | Contains returns true if the slicer contains the given value
161 |
162 | ```
163 | a := slicer.Int([]int{1,5,7,9,6,3,1,9,1})
164 | result := a.Contains(9)
165 | // result is True
166 | ```
167 |
168 | ### Join
169 |
170 | Returns a string with the slicer elements separated by the given separator
171 |
172 | ```
173 | a := slicer.String([]string{"one", "two", "three"})
174 | result := a.Join(",")
175 | // result is "one,two,three"
176 | ```
177 | ### Length
178 |
179 | Returns the length of the slice
180 |
181 | ```
182 | a := slicer.String([]string{"one", "two", "three"})
183 | result := a.Length()
184 | // result is 3
185 | ```
186 |
187 | ### Clear
188 |
189 | Clears all elements from the current slice
190 |
191 | ```
192 | a := slicer.String([]string{"one", "two", "three"})
193 | a.Clear()
194 | // a.Length() == 0
195 | ```
196 |
197 | ### Sort
198 |
199 | Sorts the elements of a slice
200 | Not supported by: InterfaceSlicer, BoolSlicer
201 |
202 | ```
203 | a := slicer.Int([]int{5,3,4,1,2})
204 | a.Sort()
205 | // a is []int{1,2,3,4,5}
206 | ```
207 |
208 | ### Deduplicate
209 |
210 | Deduplicate removes all duplicates within a slice.
211 |
212 | ```
213 | a := slicer.Int([]int{5,3,5,1,3})
214 | a.Deduplicate()
215 | // a is []int{5,3,1}
216 | ```
217 |
--------------------------------------------------------------------------------
/add_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "strings"
5 | "testing"
6 | )
7 |
8 | func TestStringAdd(t *testing.T) {
9 |
10 | s := String()
11 | s.Add("one")
12 | s.Add("two")
13 |
14 | expected := "one two"
15 | actual := strings.Join(s.AsSlice(), " ")
16 | if expected != actual {
17 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
18 | }
19 |
20 | // Add more than one value
21 | s.Clear()
22 | s.Add("one", "two")
23 | actual = strings.Join(s.AsSlice(), " ")
24 | if expected != actual {
25 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
26 | }
27 | }
28 |
29 | func TestStringAddUnique(t *testing.T) {
30 |
31 | s := String()
32 | s.AddUnique("one")
33 | s.AddUnique("one")
34 | s.AddUnique("two")
35 | s.AddUnique("two")
36 |
37 | expected := "one two"
38 | actual := strings.Join(s.AsSlice(), " ")
39 | if expected != actual {
40 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
41 | }
42 |
43 | // AddUnique more than one value
44 | s.Clear()
45 | s.AddUnique("one", "two", "two")
46 | actual = strings.Join(s.AsSlice(), " ")
47 | if expected != actual {
48 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
49 | }
50 | }
51 |
52 | func TestStringAddSlice(t *testing.T) {
53 |
54 | s := String()
55 | s.Add("one")
56 | s.Add("two")
57 | extras := []string{"three", "four"}
58 | s.AddSlice(extras)
59 |
60 | expected := "one two three four"
61 | actual := strings.Join(s.AsSlice(), " ")
62 | if expected != actual {
63 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
64 | }
65 | }
66 |
67 | func TestStringAddSlicer(t *testing.T) {
68 |
69 | s := String()
70 | s.Add("one")
71 | s.Add("two")
72 |
73 | p := String()
74 | p.Add("three")
75 | p.Add("four")
76 |
77 | s.AddSlicer(p)
78 |
79 | expected := "one two three four"
80 | actual := strings.Join(s.AsSlice(), " ")
81 | if expected != actual {
82 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/bool.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "fmt"
6 | import "strings"
7 |
8 | // BoolSlicer handles slices of bool
9 | type BoolSlicer struct {
10 | slice []bool
11 | }
12 |
13 | // Bool creates a new BoolSlicer
14 | func Bool(slice ...[]bool) *BoolSlicer {
15 | if len(slice) > 0 {
16 | return &BoolSlicer{slice: slice[0]}
17 | }
18 | return &BoolSlicer{}
19 | }
20 |
21 | // Add a bool value to the slicer
22 | func (s *BoolSlicer) Add(value bool, additional ...bool) {
23 | s.slice = append(s.slice, value)
24 | s.slice = append(s.slice, additional...)
25 | }
26 |
27 | // AddUnique adds a bool value to the slicer if it does not already exist
28 | func (s *BoolSlicer) AddUnique(value bool, additional ...bool) {
29 |
30 | if !s.Contains(value) {
31 | s.slice = append(s.slice, value)
32 | }
33 |
34 | // Add additional values
35 | for _, value := range additional {
36 | if !s.Contains(value) {
37 | s.slice = append(s.slice, value)
38 | }
39 | }
40 | }
41 |
42 | // AddSlice adds a bool slice to the slicer
43 | func (s *BoolSlicer) AddSlice(value []bool) {
44 | s.slice = append(s.slice, value...)
45 | }
46 |
47 | // AsSlice returns the slice
48 | func (s *BoolSlicer) AsSlice() []bool {
49 | return s.slice
50 | }
51 |
52 | // AddSlicer appends a BoolSlicer to the slicer
53 | func (s *BoolSlicer) AddSlicer(value *BoolSlicer) {
54 | s.slice = append(s.slice, value.AsSlice()...)
55 | }
56 |
57 | // Filter the slice based on the given function
58 | func (s *BoolSlicer) Filter(fn func(bool) bool) *BoolSlicer {
59 | result := &BoolSlicer{}
60 | for _, elem := range s.slice {
61 | if fn(elem) {
62 | result.Add(elem)
63 | }
64 | }
65 | return result
66 | }
67 |
68 | // Each runs a function on every element of the slice
69 | func (s *BoolSlicer) Each(fn func(bool)) {
70 | for _, elem := range s.slice {
71 | fn(elem)
72 | }
73 | }
74 |
75 | // Contains indicates if the given value is in the slice
76 | func (s *BoolSlicer) Contains(matcher bool) bool {
77 | result := false
78 | for _, elem := range s.slice {
79 | if elem == matcher {
80 | result = true
81 | }
82 | }
83 | return result
84 | }
85 |
86 | // Length returns the number of elements in the slice
87 | func (s *BoolSlicer) Length() int {
88 | return len(s.slice)
89 | }
90 |
91 | // Clear all elements in the slice
92 | func (s *BoolSlicer) Clear() {
93 | s.slice = []bool{}
94 | }
95 |
96 | // Deduplicate removes duplicate values from the slice
97 | func (s *BoolSlicer) Deduplicate() {
98 |
99 | result := &BoolSlicer{}
100 |
101 | for _, elem := range s.slice {
102 | if !result.Contains(elem) {
103 | result.Add(elem)
104 | }
105 | }
106 |
107 | s.slice = result.AsSlice()
108 | }
109 |
110 | // Join returns a string with the slicer elements separated by the given separator
111 | func (s *BoolSlicer) Join(separator string) string {
112 | var builder strings.Builder
113 |
114 | // Shortcut no elements
115 | if len(s.slice) == 0 {
116 | return ""
117 | }
118 |
119 | // Iterate over length - 1
120 | index := 0
121 | for index = 0; index < len(s.slice)-1; index++ {
122 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
123 | }
124 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
125 | result := builder.String()
126 | return result
127 | }
128 |
--------------------------------------------------------------------------------
/bool_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "testing"
7 | )
8 |
9 | func TestBoolAddUnique(t *testing.T) {
10 |
11 | s := Bool()
12 | s.AddUnique(true)
13 | s.AddUnique(true)
14 |
15 | expected := "[true]"
16 | actual, _ := json.Marshal(s.AsSlice())
17 | if expected != string(actual) {
18 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
19 | }
20 |
21 | s.Clear()
22 | s.AddUnique(true, false)
23 |
24 | expected = "[true,false]"
25 | actual, _ = json.Marshal(s.AsSlice())
26 | if expected != string(actual) {
27 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
28 | }
29 | }
30 | func TestBoolAdd(t *testing.T) {
31 |
32 | s := Bool()
33 | s.Add(true)
34 | s.Add(false)
35 |
36 | expected := "[true,false]"
37 | actual, _ := json.Marshal(s.AsSlice())
38 | if expected != string(actual) {
39 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
40 | }
41 |
42 | s.Clear()
43 | s.Add(true, false)
44 |
45 | expected = "[true,false]"
46 | actual, _ = json.Marshal(s.AsSlice())
47 | if expected != string(actual) {
48 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
49 | }
50 | }
51 |
52 | func TestBoolAddSlice(t *testing.T) {
53 |
54 | s := Bool()
55 | s.Add(true)
56 | s.Add(false)
57 |
58 | extras := []bool{true, false}
59 |
60 | s.AddSlice(extras)
61 |
62 | expected := "[true,false,true,false]"
63 | actual, _ := json.Marshal(s.AsSlice())
64 | if expected != string(actual) {
65 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
66 | }
67 | }
68 |
69 | func TestBoolAddSlicer(t *testing.T) {
70 |
71 | s := Bool()
72 | s.Add(true)
73 | s.Add(false)
74 |
75 | p := Bool()
76 | p.Add(true)
77 | p.Add(false)
78 |
79 | s.AddSlicer(p)
80 |
81 | expected := "[true,false,true,false]"
82 | actual, _ := json.Marshal(s.AsSlice())
83 | if expected != string(actual) {
84 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
85 | }
86 | }
87 |
88 | func TestBoolFilter(t *testing.T) {
89 |
90 | s := Bool()
91 | s.Add(true)
92 | s.Add(false)
93 | s.Add(true)
94 | s.Add(true)
95 | s.Add(false)
96 |
97 | result := s.Filter(func(i bool) bool {
98 | return i == true
99 | })
100 |
101 | expected := 3
102 | actual := len(result.AsSlice())
103 | if actual != expected {
104 | t.Errorf("Expected '%d', but got '%d'", expected, actual)
105 | }
106 | }
107 |
108 | func TestBoolEach(t *testing.T) {
109 |
110 | s := Bool()
111 | s.Add(true)
112 | s.Add(false)
113 | s.Add(true)
114 | s.Add(true)
115 | s.Add(false)
116 |
117 | result := ""
118 | s.Each(func(i bool) {
119 | result += fmt.Sprintf("%t", i)
120 | })
121 |
122 | var expected = "truefalsetruetruefalse"
123 | if expected != result {
124 | t.Errorf("Expected '%s', but got '%s'", expected, result)
125 | }
126 | }
127 |
128 | // TestOptionalBoolSlice tests
129 | func TestOptionalBoolSlice(t *testing.T) {
130 | data := []bool{true, false}
131 | s := Bool(data)
132 |
133 | var result string
134 | s.Each(func(elem bool) {
135 | result += fmt.Sprintf("%t", elem)
136 | })
137 | var expected = "truefalse"
138 | if expected != result {
139 | t.Errorf("Expected '%s', but got '%s'", expected, result)
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/clear_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import "testing"
4 |
5 | func TestStringClear(t *testing.T) {
6 | data := []string{"cat", "bat", "dog", "arachnid"}
7 | s := String(data)
8 |
9 | expected := 4
10 | result := s.Length()
11 | if result != expected {
12 | t.Errorf("Expected %d, but got %d", expected, result)
13 | }
14 | s.Clear()
15 | if s.Length() != 0 {
16 | t.Errorf("Expected %d, but got %d", expected, result)
17 | }
18 | }
19 |
20 | func TestInterfaceClear(t *testing.T) {
21 |
22 | s := Interface()
23 | var a interface{} = 1
24 | var b interface{} = "hello"
25 | s.Add(a)
26 | s.Add(b)
27 |
28 | expected := 2
29 | result := s.Length()
30 | if result != expected {
31 | t.Errorf("Expected %d, but got %d", expected, result)
32 | }
33 | s.Clear()
34 | if s.Length() != 0 {
35 | t.Errorf("Expected %d, but got %d", expected, result)
36 | }
37 | }
38 | func TestInt32Clear(t *testing.T) {
39 |
40 | data := []int32{1, 2, 3}
41 | s := Int32(data)
42 |
43 | expected := 3
44 | result := s.Length()
45 | if result != expected {
46 | t.Errorf("Expected %d, but got %d", expected, result)
47 | }
48 | s.Clear()
49 | if s.Length() != 0 {
50 | t.Errorf("Expected %d, but got %d", expected, result)
51 | }
52 | }
53 |
54 | func TestInt16Clear(t *testing.T) {
55 |
56 | data := []int16{1, 2, 3}
57 | s := Int16(data)
58 |
59 | expected := 3
60 | result := s.Length()
61 | if result != expected {
62 | t.Errorf("Expected %d, but got %d", expected, result)
63 | }
64 | s.Clear()
65 | if s.Length() != 0 {
66 | t.Errorf("Expected %d, but got %d", expected, result)
67 | }
68 | }
69 |
70 | func TestInt8Clear(t *testing.T) {
71 |
72 | data := []int8{1, 2, 3}
73 | s := Int8(data)
74 |
75 | expected := 3
76 | result := s.Length()
77 | if result != expected {
78 | t.Errorf("Expected %d, but got %d", expected, result)
79 | }
80 | s.Clear()
81 | if s.Length() != 0 {
82 | t.Errorf("Expected %d, but got %d", expected, result)
83 | }
84 | }
85 |
86 | func TestIntClear(t *testing.T) {
87 |
88 | data := []int{1, 2, 3}
89 | s := Int(data)
90 |
91 | expected := 3
92 | result := s.Length()
93 | if result != expected {
94 | t.Errorf("Expected %d, but got %d", expected, result)
95 | }
96 | s.Clear()
97 | if s.Length() != 0 {
98 | t.Errorf("Expected %d, but got %d", expected, result)
99 | }
100 | }
101 |
102 | func TestBoolClear(t *testing.T) {
103 |
104 | data := []bool{true}
105 | s := Bool(data)
106 |
107 | expected := 1
108 | result := s.Length()
109 | if result != expected {
110 | t.Errorf("Expected %d, but got %d", expected, result)
111 | }
112 | s.Clear()
113 | if s.Length() != 0 {
114 | t.Errorf("Expected %d, but got %d", expected, result)
115 | }
116 | }
117 |
118 | func TestFloat64Clear(t *testing.T) {
119 |
120 | data := []float64{1.4, 2.1, 3}
121 | s := Float64(data)
122 |
123 | expected := 3
124 | result := s.Length()
125 | if result != expected {
126 | t.Errorf("Expected %d, but got %d", expected, result)
127 | }
128 | s.Clear()
129 | if s.Length() != 0 {
130 | t.Errorf("Expected %d, but got %d", expected, result)
131 | }
132 | }
133 | func TestFloat32Clear(t *testing.T) {
134 |
135 | data := []float32{1.4, 2.1, 3}
136 | s := Float32(data)
137 |
138 | expected := 3
139 | result := s.Length()
140 | if result != expected {
141 | t.Errorf("Expected %d, but got %d", expected, result)
142 | }
143 | s.Clear()
144 | if s.Length() != 0 {
145 | t.Errorf("Expected %d, but got %d", expected, result)
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/contains_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import "testing"
4 |
5 | func TestStringContains(t *testing.T) {
6 | data := []string{"cat", "bat", "dog", "arachnid"}
7 | s := String(data)
8 |
9 | // Positive test
10 | expected := true
11 | result := s.Contains("cat")
12 | if result != expected {
13 | t.Errorf("Expected '%t', but got '%t'", expected, result)
14 | }
15 |
16 | // Negative test
17 | expected = false
18 | result = s.Contains("horse")
19 | if result != expected {
20 | t.Errorf("Expected '%t', but got '%t'", expected, result)
21 | }
22 | }
23 |
24 | func TestInterfaceContains(t *testing.T) {
25 |
26 | s := Interface()
27 | var a interface{} = 1
28 | var b interface{} = "hello"
29 | s.Add(a)
30 | s.Add(b)
31 |
32 | // Positive test
33 | expected := true
34 | result := s.Contains(a)
35 | if result != expected {
36 | t.Errorf("Expected '%t', but got '%t'", expected, result)
37 | }
38 |
39 | // Negative test
40 | expected = false
41 | var dummy interface{} = 5
42 | result = s.Contains(dummy)
43 | if result != expected {
44 | t.Errorf("Expected '%t', but got '%t'", expected, result)
45 | }
46 | }
47 |
48 | func TestInt64Contains(t *testing.T) {
49 |
50 | data := []int64{1, 2, 3}
51 | s := Int64(data)
52 |
53 | // Positive test
54 | expected := true
55 | result := s.Contains(2)
56 | if result != expected {
57 | t.Errorf("Expected '%t', but got '%t'", expected, result)
58 | }
59 |
60 | // Negative test
61 | expected = false
62 | var badValue int64 = 9
63 | result = s.Contains(badValue)
64 | if result != expected {
65 | t.Errorf("Expected '%t', but got '%t'", expected, result)
66 | }
67 | }
68 | func TestInt32Contains(t *testing.T) {
69 |
70 | data := []int32{1, 2, 3}
71 | s := Int32(data)
72 |
73 | // Positive test
74 | expected := true
75 | result := s.Contains(2)
76 | if result != expected {
77 | t.Errorf("Expected '%t', but got '%t'", expected, result)
78 | }
79 |
80 | // Negative test
81 | expected = false
82 | var badValue int32 = 9
83 | result = s.Contains(badValue)
84 | if result != expected {
85 | t.Errorf("Expected '%t', but got '%t'", expected, result)
86 | }
87 | }
88 |
89 | func TestInt16Contains(t *testing.T) {
90 |
91 | data := []int16{1, 2, 3}
92 | s := Int16(data)
93 |
94 | // Positive test
95 | expected := true
96 | result := s.Contains(2)
97 | if result != expected {
98 | t.Errorf("Expected '%t', but got '%t'", expected, result)
99 | }
100 |
101 | // Negative test
102 | expected = false
103 | var badValue int16 = 9
104 | result = s.Contains(badValue)
105 | if result != expected {
106 | t.Errorf("Expected '%t', but got '%t'", expected, result)
107 | }
108 | }
109 |
110 | func TestInt8Contains(t *testing.T) {
111 |
112 | data := []int8{1, 2, 3}
113 | s := Int8(data)
114 |
115 | // Positive test
116 | expected := true
117 | result := s.Contains(2)
118 | if result != expected {
119 | t.Errorf("Expected '%t', but got '%t'", expected, result)
120 | }
121 |
122 | // Negative test
123 | expected = false
124 | var badValue int8 = 9
125 | result = s.Contains(badValue)
126 | if result != expected {
127 | t.Errorf("Expected '%t', but got '%t'", expected, result)
128 | }
129 | }
130 |
131 | func TestIntContains(t *testing.T) {
132 |
133 | data := []int{1, 2, 3}
134 | s := Int(data)
135 |
136 | // Positive test
137 | expected := true
138 | result := s.Contains(2)
139 | if result != expected {
140 | t.Errorf("Expected '%t', but got '%t'", expected, result)
141 | }
142 |
143 | // Negative test
144 | expected = false
145 | var badValue int = 9
146 | result = s.Contains(badValue)
147 | if result != expected {
148 | t.Errorf("Expected '%t', but got '%t'", expected, result)
149 | }
150 | }
151 |
152 | func TestBoolContains(t *testing.T) {
153 |
154 | data := []bool{true}
155 | s := Bool(data)
156 |
157 | // Positive test
158 | expected := true
159 | result := s.Contains(true)
160 | if result != expected {
161 | t.Errorf("Expected '%t', but got '%t'", expected, result)
162 | }
163 |
164 | // Negative test
165 | expected = false
166 | result = s.Contains(false)
167 | if result != expected {
168 | t.Errorf("Expected '%t', but got '%t'", expected, result)
169 | }
170 | }
171 |
172 | func TestFloat64Contains(t *testing.T) {
173 |
174 | data := []float64{1.4, 2.1, 3}
175 | s := Float64(data)
176 |
177 | // Positive test
178 | expected := true
179 | result := s.Contains(2.1)
180 | if result != expected {
181 | t.Errorf("Expected '%t', but got '%t'", expected, result)
182 | }
183 |
184 | // Negative test
185 | expected = false
186 | result = s.Contains(9.43)
187 | if result != expected {
188 | t.Errorf("Expected '%t', but got '%t'", expected, result)
189 | }
190 | }
191 | func TestFloat32Contains(t *testing.T) {
192 |
193 | data := []float32{1.4, 2.1, 3}
194 | s := Float32(data)
195 |
196 | // Positive test
197 | expected := true
198 | result := s.Contains(2.1)
199 | if result != expected {
200 | t.Errorf("Expected '%t', but got '%t'", expected, result)
201 | }
202 |
203 | // Negative test
204 | expected = false
205 | result = s.Contains(9.43)
206 | if result != expected {
207 | t.Errorf("Expected '%t', but got '%t'", expected, result)
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/deduplicate_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "strings"
6 | "testing"
7 | )
8 |
9 | func TestStringDeduplicate(t *testing.T) {
10 |
11 | s := String()
12 | s.Add("one", "four", "two", "three", "two", "one")
13 |
14 | s.Deduplicate()
15 | expected := "one four two three"
16 | actual := strings.Join(s.AsSlice(), " ")
17 | if expected != actual {
18 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
19 | }
20 | }
21 |
22 | func TestInt64Deduplicate(t *testing.T) {
23 |
24 | s := Int64()
25 | s.Add(1, 2, 3, 2, 3, 4, 3, 4, 5)
26 |
27 | s.Deduplicate()
28 | expected := "[1,2,3,4,5]"
29 | actual, _ := json.Marshal(s.AsSlice())
30 | if expected != string(actual) {
31 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
32 | }
33 | }
34 |
35 | func TestInt32Deduplicate(t *testing.T) {
36 |
37 | s := Int32()
38 | s.Add(1, 2, 3, 2, 3, 4, 3, 4, 5)
39 |
40 | s.Deduplicate()
41 | expected := "[1,2,3,4,5]"
42 | actual, _ := json.Marshal(s.AsSlice())
43 | if expected != string(actual) {
44 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
45 | }
46 | }
47 |
48 | func TestInt16Deduplicate(t *testing.T) {
49 |
50 | s := Int16()
51 | s.Add(1, 2, 3, 2, 3, 4, 3, 4, 5)
52 |
53 | s.Deduplicate()
54 | expected := "[1,2,3,4,5]"
55 | actual, _ := json.Marshal(s.AsSlice())
56 | if expected != string(actual) {
57 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
58 | }
59 | }
60 |
61 | func TestInt8Deduplicate(t *testing.T) {
62 |
63 | s := Int8()
64 | s.Add(1, 2, 3, 2, 3, 4, 3, 4, 5)
65 |
66 | s.Deduplicate()
67 | expected := "[1,2,3,4,5]"
68 | actual, _ := json.Marshal(s.AsSlice())
69 | if expected != string(actual) {
70 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
71 | }
72 | }
73 |
74 | func TestIntDeduplicate(t *testing.T) {
75 |
76 | s := Int()
77 | s.Add(1, 2, 3, 2, 3, 4, 3, 4, 5)
78 |
79 | s.Deduplicate()
80 | expected := "[1,2,3,4,5]"
81 | actual, _ := json.Marshal(s.AsSlice())
82 | if expected != string(actual) {
83 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
84 | }
85 | }
86 |
87 | func TestInterfaceDeduplicate(t *testing.T) {
88 |
89 | s := Interface()
90 | var a interface{} = 1
91 | var b interface{} = "hello"
92 | s.Add(a, b, a, b)
93 |
94 | s.Deduplicate()
95 | expected := `[1,"hello"]`
96 | actual, _ := json.Marshal(s.AsSlice())
97 | if expected != string(actual) {
98 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
99 | }
100 | }
101 |
102 | func TestFloat32Deduplicate(t *testing.T) {
103 |
104 | s := Float32()
105 | s.Add(1.5, 2.3, 3.9, 2.3, 3.9, 4.4, 3.9, 4.4, 5.2)
106 |
107 | s.Deduplicate()
108 | expected := "[1.5,2.3,3.9,4.4,5.2]"
109 | actual, _ := json.Marshal(s.AsSlice())
110 | if expected != string(actual) {
111 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
112 | }
113 | }
114 |
115 | func TestFloat64Deduplicate(t *testing.T) {
116 |
117 | s := Float64()
118 | s.Add(1.5, 2.3, 3.9, 2.3, 3.9, 4.4, 3.9, 4.4, 5.2)
119 |
120 | s.Deduplicate()
121 | expected := "[1.5,2.3,3.9,4.4,5.2]"
122 | actual, _ := json.Marshal(s.AsSlice())
123 | if expected != string(actual) {
124 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
125 | }
126 | }
127 |
128 | func TestBoolDeduplicate(t *testing.T) {
129 |
130 | s := Bool()
131 | s.Add(true, true, true, false, true, false, false, false)
132 |
133 | s.Deduplicate()
134 | expected := "[true,false]"
135 | actual, _ := json.Marshal(s.AsSlice())
136 | if expected != string(actual) {
137 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
138 | }
139 | }
140 |
141 | // func TestStringAddSlice(t *testing.T) {
142 |
143 | // s := String()
144 | // s.Add("one")
145 | // s.Add("two")
146 | // extras := []string{"three", "four"}
147 | // s.AddSlice(extras)
148 |
149 | // expected := "one two three four"
150 | // actual := strings.Join(s.AsSlice(), " ")
151 | // if expected != actual {
152 | // t.Errorf("Expected '%s', but got '%s'", expected, actual)
153 | // }
154 | // }
155 |
156 | // func TestStringAddSlicer(t *testing.T) {
157 |
158 | // s := String()
159 | // s.Add("one")
160 | // s.Add("two")
161 |
162 | // p := String()
163 | // p.Add("three")
164 | // p.Add("four")
165 |
166 | // s.AddSlicer(p)
167 |
168 | // expected := "one two three four"
169 | // actual := strings.Join(s.AsSlice(), " ")
170 | // if expected != actual {
171 | // t.Errorf("Expected '%s', but got '%s'", expected, actual)
172 | // }
173 | // }
174 |
--------------------------------------------------------------------------------
/float32.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Float32Slicer handles slices of float32
10 | type Float32Slicer struct {
11 | slice []float32
12 | }
13 |
14 | // Float32 creates a new Float32Slicer
15 | func Float32(slice ...[]float32) *Float32Slicer {
16 | if len(slice) > 0 {
17 | return &Float32Slicer{slice: slice[0]}
18 | }
19 | return &Float32Slicer{}
20 | }
21 |
22 | // Add a float32 value to the slicer
23 | func (s *Float32Slicer) Add(value float32, additional ...float32) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a float32 value to the slicer if it does not already exist
29 | func (s *Float32Slicer) AddUnique(value float32, additional ...float32) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a float32 slice to the slicer
44 | func (s *Float32Slicer) AddSlice(value []float32) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Float32Slicer) AsSlice() []float32 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Float32Slicer to the slicer
54 | func (s *Float32Slicer) AddSlicer(value *Float32Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Float32Slicer) Filter(fn func(float32) bool) *Float32Slicer {
60 | result := &Float32Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Float32Slicer) Each(fn func(float32)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Float32Slicer) Contains(matcher float32) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Float32Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Float32Slicer) Clear() {
94 | s.slice = []float32{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Float32Slicer) Deduplicate() {
99 |
100 | result := &Float32Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Float32Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Float32Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/float32_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "testing"
7 | )
8 |
9 | func TestFloat32Add(t *testing.T) {
10 |
11 | s := Float32()
12 | s.Add(1.1)
13 | s.Add(2.5)
14 |
15 | expected := "[1.1,2.5]"
16 | actual, _ := json.Marshal(s.AsSlice())
17 | if expected != string(actual) {
18 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
19 | }
20 |
21 | s.Clear()
22 | s.Add(1.1, 2.5)
23 |
24 | expected = "[1.1,2.5]"
25 | actual, _ = json.Marshal(s.AsSlice())
26 | if expected != string(actual) {
27 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
28 | }
29 | }
30 | func TestFloat32AddUnique(t *testing.T) {
31 |
32 | s := Float32()
33 | s.AddUnique(1.1)
34 | s.AddUnique(1.1)
35 | s.AddUnique(2.5)
36 |
37 | expected := "[1.1,2.5]"
38 | actual, _ := json.Marshal(s.AsSlice())
39 | if expected != string(actual) {
40 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
41 | }
42 |
43 | s.Clear()
44 | s.AddUnique(1.1, 2.5, 2.5)
45 |
46 | expected = "[1.1,2.5]"
47 | actual, _ = json.Marshal(s.AsSlice())
48 | if expected != string(actual) {
49 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
50 | }
51 | }
52 |
53 | func TestFloat32AddSlice(t *testing.T) {
54 |
55 | s := Float32()
56 | s.Add(1.1)
57 | s.Add(2.2)
58 |
59 | extras := []float32{3.3, 4.4}
60 |
61 | s.AddSlice(extras)
62 |
63 | expected := "[1.1,2.2,3.3,4.4]"
64 | actual, _ := json.Marshal(s.AsSlice())
65 | if expected != string(actual) {
66 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
67 | }
68 | }
69 |
70 | func TestFloat32AddSlicer(t *testing.T) {
71 |
72 | s := Float32()
73 | s.Add(1.1)
74 | s.Add(2.2)
75 |
76 | p := Float32()
77 | p.Add(3.3)
78 | p.Add(4.4)
79 |
80 | s.AddSlicer(p)
81 |
82 | expected := "[1.1,2.2,3.3,4.4]"
83 | actual, _ := json.Marshal(s.AsSlice())
84 | if expected != string(actual) {
85 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
86 | }
87 | }
88 |
89 | func TestFloat32Filter(t *testing.T) {
90 |
91 | s := Float32()
92 | s.Add(0.1)
93 | s.Add(0.4)
94 | s.Add(0.3)
95 | s.Add(0.8)
96 | s.Add(0.5)
97 | s.Add(1.3)
98 | s.Add(3.9)
99 | s.Add(0.4)
100 |
101 | result := s.Filter(func(i float32) bool {
102 | return i < 0.5
103 | })
104 |
105 | expected := "[0.1,0.4,0.3,0.4]"
106 | actual, _ := json.Marshal(result.AsSlice())
107 | if expected != string(actual) {
108 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
109 | }
110 | }
111 |
112 | func TestFloat32Each(t *testing.T) {
113 |
114 | s := Float32()
115 | s.Add(0.1)
116 | s.Add(0.4)
117 | s.Add(0.3)
118 | s.Add(0.8)
119 | s.Add(0.5)
120 | s.Add(1.3)
121 | s.Add(3.9)
122 | s.Add(0.4)
123 |
124 | var result float32
125 | s.Each(func(i float32) {
126 | result += i
127 | })
128 |
129 | var expected = 7.7
130 | if fmt.Sprintf("%f", expected) != fmt.Sprintf("%f", result) {
131 | t.Errorf("Expected '%f', but got '%f'", expected, result)
132 | }
133 | }
134 |
135 | // TestOptionalFloat32Slice tests when you construct a Float32 with
136 | // an existing slice
137 | func TestOptionalFloat32Slice(t *testing.T) {
138 | data := []float32{1, 2, 3}
139 | s := Float32(data)
140 |
141 | var result float32
142 | s.Each(func(elem float32) {
143 | result += elem
144 | })
145 | var expected float32 = 6.0
146 | if expected != result {
147 | t.Errorf("Expected '%f', but got '%f'", expected, result)
148 | }
149 | }
150 |
151 | // TestFloat32Sort tests that the slicer can be sorted
152 | func TestFloat32Sort(t *testing.T) {
153 | data := []float32{5, 4, 3, 2, 1}
154 | s := Float32(data)
155 | s.Sort()
156 | result := s.Join(",")
157 | expected := "1,2,3,4,5"
158 | if expected != result {
159 | t.Errorf("Expected '%s', but got '%s'", expected, result)
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/float64.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Float64Slicer handles slices of float64
10 | type Float64Slicer struct {
11 | slice []float64
12 | }
13 |
14 | // Float64 creates a new Float64Slicer
15 | func Float64(slice ...[]float64) *Float64Slicer {
16 | if len(slice) > 0 {
17 | return &Float64Slicer{slice: slice[0]}
18 | }
19 | return &Float64Slicer{}
20 | }
21 |
22 | // Add a float64 value to the slicer
23 | func (s *Float64Slicer) Add(value float64, additional ...float64) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a float64 value to the slicer if it does not already exist
29 | func (s *Float64Slicer) AddUnique(value float64, additional ...float64) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a float64 slice to the slicer
44 | func (s *Float64Slicer) AddSlice(value []float64) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Float64Slicer) AsSlice() []float64 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Float64Slicer to the slicer
54 | func (s *Float64Slicer) AddSlicer(value *Float64Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Float64Slicer) Filter(fn func(float64) bool) *Float64Slicer {
60 | result := &Float64Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Float64Slicer) Each(fn func(float64)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Float64Slicer) Contains(matcher float64) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Float64Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Float64Slicer) Clear() {
94 | s.slice = []float64{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Float64Slicer) Deduplicate() {
99 |
100 | result := &Float64Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Float64Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Float64Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/float64_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "testing"
7 | )
8 |
9 | func TestFloat64Add(t *testing.T) {
10 |
11 | s := Float64()
12 | s.Add(1.1)
13 | s.Add(2.5)
14 |
15 | expected := "[1.1,2.5]"
16 | actual, _ := json.Marshal(s.AsSlice())
17 | if expected != string(actual) {
18 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
19 | }
20 | s.Clear()
21 | s.Add(1.1, 2.5)
22 |
23 | expected = "[1.1,2.5]"
24 | actual, _ = json.Marshal(s.AsSlice())
25 | if expected != string(actual) {
26 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
27 | }
28 | }
29 | func TestFloat64AddUnique(t *testing.T) {
30 |
31 | s := Float64()
32 | s.AddUnique(1.1)
33 | s.AddUnique(2.5)
34 | s.AddUnique(2.5)
35 |
36 | expected := "[1.1,2.5]"
37 | actual, _ := json.Marshal(s.AsSlice())
38 | if expected != string(actual) {
39 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
40 | }
41 | s.Clear()
42 | s.AddUnique(1.1, 2.5, 1.1)
43 |
44 | expected = "[1.1,2.5]"
45 | actual, _ = json.Marshal(s.AsSlice())
46 | if expected != string(actual) {
47 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
48 | }
49 | }
50 |
51 | func TestFloat64AddSlice(t *testing.T) {
52 |
53 | s := Float64()
54 | s.Add(1.1)
55 | s.Add(2.2)
56 |
57 | extras := []float64{3.3, 4.4}
58 |
59 | s.AddSlice(extras)
60 |
61 | expected := "[1.1,2.2,3.3,4.4]"
62 | actual, _ := json.Marshal(s.AsSlice())
63 | if expected != string(actual) {
64 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
65 | }
66 | }
67 |
68 | func TestFloat64AddSlicer(t *testing.T) {
69 |
70 | s := Float64()
71 | s.Add(1.1)
72 | s.Add(2.2)
73 |
74 | p := Float64()
75 | p.Add(3.3)
76 | p.Add(4.4)
77 |
78 | s.AddSlicer(p)
79 |
80 | expected := "[1.1,2.2,3.3,4.4]"
81 | actual, _ := json.Marshal(s.AsSlice())
82 | if expected != string(actual) {
83 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
84 | }
85 | }
86 |
87 | func TestFloat64Filter(t *testing.T) {
88 |
89 | s := Float64()
90 | s.Add(0.1)
91 | s.Add(0.4)
92 | s.Add(0.3)
93 | s.Add(0.8)
94 | s.Add(0.5)
95 | s.Add(1.3)
96 | s.Add(3.9)
97 | s.Add(0.4)
98 |
99 | result := s.Filter(func(i float64) bool {
100 | return i < 0.5
101 | })
102 |
103 | expected := "[0.1,0.4,0.3,0.4]"
104 | actual, _ := json.Marshal(result.AsSlice())
105 | if expected != string(actual) {
106 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
107 | }
108 | }
109 |
110 | func TestFloat64Each(t *testing.T) {
111 |
112 | s := Float64()
113 | s.Add(0.1)
114 | s.Add(0.4)
115 | s.Add(0.3)
116 | s.Add(0.8)
117 | s.Add(0.5)
118 | s.Add(1.3)
119 | s.Add(3.9)
120 | s.Add(0.4)
121 |
122 | var result float64
123 | s.Each(func(i float64) {
124 | result += i
125 | })
126 |
127 | var expected = 7.7
128 | if fmt.Sprintf("%f", expected) != fmt.Sprintf("%f", result) {
129 | t.Errorf("Expected '%f', but got '%f'", expected, result)
130 | }
131 | }
132 |
133 | // TestOptionalFloat64Slice tests when you construct a Float64 with
134 | // an existing slice
135 | func TestOptionalFloat64Slice(t *testing.T) {
136 | data := []float64{1, 2, 3}
137 | s := Float64(data)
138 |
139 | var result float64
140 | s.Each(func(elem float64) {
141 | result += elem
142 | })
143 | var expected = 6.0
144 | if expected != result {
145 | t.Errorf("Expected '%f', but got '%f'", expected, result)
146 | }
147 | }
148 |
149 | // TestFloat64Sort tests that the slicer can be sorted
150 | func TestFloat64Sort(t *testing.T) {
151 | data := []float64{5, 4, 3, 2, 1}
152 | s := Float64(data)
153 | s.Sort()
154 | result := s.Join(",")
155 | expected := "1,2,3,4,5"
156 | if expected != result {
157 | t.Errorf("Expected '%s', but got '%s'", expected, result)
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/leaanthony/slicer
2 |
3 | go 1.13
4 |
5 | require github.com/matryer/is v1.4.0
6 |
--------------------------------------------------------------------------------
/int.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // IntSlicer handles slices of int
10 | type IntSlicer struct {
11 | slice []int
12 | }
13 |
14 | // Int creates a new IntSlicer
15 | func Int(slice ...[]int) *IntSlicer {
16 | if len(slice) > 0 {
17 | return &IntSlicer{slice: slice[0]}
18 | }
19 | return &IntSlicer{}
20 | }
21 |
22 | // Add a int value to the slicer
23 | func (s *IntSlicer) Add(value int, additional ...int) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a int value to the slicer if it does not already exist
29 | func (s *IntSlicer) AddUnique(value int, additional ...int) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a int slice to the slicer
44 | func (s *IntSlicer) AddSlice(value []int) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *IntSlicer) AsSlice() []int {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a IntSlicer to the slicer
54 | func (s *IntSlicer) AddSlicer(value *IntSlicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *IntSlicer) Filter(fn func(int) bool) *IntSlicer {
60 | result := &IntSlicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *IntSlicer) Each(fn func(int)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *IntSlicer) Contains(matcher int) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *IntSlicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *IntSlicer) Clear() {
94 | s.slice = []int{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *IntSlicer) Deduplicate() {
99 |
100 | result := &IntSlicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *IntSlicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *IntSlicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/int16.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Int16Slicer handles slices of int16
10 | type Int16Slicer struct {
11 | slice []int16
12 | }
13 |
14 | // Int16 creates a new Int16Slicer
15 | func Int16(slice ...[]int16) *Int16Slicer {
16 | if len(slice) > 0 {
17 | return &Int16Slicer{slice: slice[0]}
18 | }
19 | return &Int16Slicer{}
20 | }
21 |
22 | // Add a int16 value to the slicer
23 | func (s *Int16Slicer) Add(value int16, additional ...int16) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a int16 value to the slicer if it does not already exist
29 | func (s *Int16Slicer) AddUnique(value int16, additional ...int16) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a int16 slice to the slicer
44 | func (s *Int16Slicer) AddSlice(value []int16) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Int16Slicer) AsSlice() []int16 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Int16Slicer to the slicer
54 | func (s *Int16Slicer) AddSlicer(value *Int16Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Int16Slicer) Filter(fn func(int16) bool) *Int16Slicer {
60 | result := &Int16Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Int16Slicer) Each(fn func(int16)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Int16Slicer) Contains(matcher int16) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Int16Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Int16Slicer) Clear() {
94 | s.slice = []int16{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Int16Slicer) Deduplicate() {
99 |
100 | result := &Int16Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Int16Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Int16Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/int16_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 | )
7 |
8 | func TestInt16Add(t *testing.T) {
9 |
10 | s := Int16()
11 | s.Add(1)
12 | s.Add(2)
13 |
14 | expected := "[1,2]"
15 | actual, _ := json.Marshal(s.AsSlice())
16 | if expected != string(actual) {
17 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
18 | }
19 |
20 | s.Clear()
21 | s.Add(1, 2)
22 |
23 | expected = "[1,2]"
24 | actual, _ = json.Marshal(s.AsSlice())
25 | if expected != string(actual) {
26 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
27 | }
28 | }
29 |
30 | func TestInt16AddUnique(t *testing.T) {
31 |
32 | s := Int16()
33 | s.AddUnique(1)
34 | s.AddUnique(2)
35 | s.AddUnique(2)
36 | s.AddUnique(2)
37 |
38 | expected := "[1,2]"
39 | actual, _ := json.Marshal(s.AsSlice())
40 | if expected != string(actual) {
41 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
42 | }
43 |
44 | s.Clear()
45 | s.AddUnique(1, 2, 1, 2, 2, 1)
46 |
47 | expected = "[1,2]"
48 | actual, _ = json.Marshal(s.AsSlice())
49 | if expected != string(actual) {
50 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
51 | }
52 | }
53 |
54 | func TestInt16AddSlice(t *testing.T) {
55 |
56 | s := Int16()
57 | s.Add(1)
58 | s.Add(2)
59 |
60 | extras := []int16{3, 4}
61 |
62 | s.AddSlice(extras)
63 |
64 | expected := "[1,2,3,4]"
65 | actual, _ := json.Marshal(s.AsSlice())
66 | if expected != string(actual) {
67 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
68 | }
69 | }
70 |
71 | func TestInt16AddSlicer(t *testing.T) {
72 |
73 | s := Int16()
74 | s.Add(1)
75 | s.Add(2)
76 |
77 | p := Int16()
78 | p.Add(3)
79 | p.Add(4)
80 |
81 | s.AddSlicer(p)
82 |
83 | expected := "[1,2,3,4]"
84 | actual, _ := json.Marshal(s.AsSlice())
85 | if expected != string(actual) {
86 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
87 | }
88 | }
89 | func TestInt16Filter(t *testing.T) {
90 |
91 | s := Int16()
92 | s.Add(18)
93 | s.Add(180)
94 | s.Add(1)
95 | s.Add(10)
96 | s.Add(20)
97 | s.Add(3)
98 | s.Add(29)
99 |
100 | result := s.Filter(func(i int16) bool {
101 | return i > 19
102 | })
103 |
104 | expected := "[180,20,29]"
105 | actual, _ := json.Marshal(result.AsSlice())
106 | if expected != string(actual) {
107 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
108 | }
109 | }
110 | func TestInt16Each(t *testing.T) {
111 |
112 | s := Int16()
113 | s.Add(18)
114 | s.Add(10)
115 | s.Add(1)
116 | s.Add(10)
117 | s.Add(20)
118 | s.Add(3)
119 | s.Add(29)
120 |
121 | var result int16
122 |
123 | s.Each(func(i int16) {
124 | result = result + i
125 | })
126 |
127 | var expected int16 = 91
128 | if expected != result {
129 | t.Errorf("Expected '%d', but got '%d'", expected, result)
130 | }
131 | }
132 |
133 | // TestOptionalInt16Slice tests when you construct a Int16 with
134 | // an existing slice
135 | func TestOptionalInt16Slice(t *testing.T) {
136 | data := []int16{1, 2, 3}
137 | s := Int16(data)
138 |
139 | var result int16 = 0
140 | s.Each(func(elem int16) {
141 | result += elem
142 | })
143 | var expected int16 = 6
144 | if expected != result {
145 | t.Errorf("Expected '%d', but got '%d'", expected, result)
146 | }
147 | }
148 |
149 | // TestInt16Sort tests that the slicer can be sorted
150 | func TestInt16Sort(t *testing.T) {
151 | data := []int16{5, 4, 3, 2, 1}
152 | s := Int16(data)
153 | s.Sort()
154 | result := s.Join(",")
155 | expected := "1,2,3,4,5"
156 | if expected != result {
157 | t.Errorf("Expected '%s', but got '%s'", expected, result)
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/int32.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Int32Slicer handles slices of int32
10 | type Int32Slicer struct {
11 | slice []int32
12 | }
13 |
14 | // Int32 creates a new Int32Slicer
15 | func Int32(slice ...[]int32) *Int32Slicer {
16 | if len(slice) > 0 {
17 | return &Int32Slicer{slice: slice[0]}
18 | }
19 | return &Int32Slicer{}
20 | }
21 |
22 | // Add a int32 value to the slicer
23 | func (s *Int32Slicer) Add(value int32, additional ...int32) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a int32 value to the slicer if it does not already exist
29 | func (s *Int32Slicer) AddUnique(value int32, additional ...int32) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a int32 slice to the slicer
44 | func (s *Int32Slicer) AddSlice(value []int32) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Int32Slicer) AsSlice() []int32 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Int32Slicer to the slicer
54 | func (s *Int32Slicer) AddSlicer(value *Int32Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Int32Slicer) Filter(fn func(int32) bool) *Int32Slicer {
60 | result := &Int32Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Int32Slicer) Each(fn func(int32)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Int32Slicer) Contains(matcher int32) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Int32Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Int32Slicer) Clear() {
94 | s.slice = []int32{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Int32Slicer) Deduplicate() {
99 |
100 | result := &Int32Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Int32Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Int32Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/int32_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 | )
7 |
8 | func TestInt32Add(t *testing.T) {
9 |
10 | s := Int32()
11 | s.Add(1)
12 | s.Add(2)
13 |
14 | expected := "[1,2]"
15 | actual, _ := json.Marshal(s.AsSlice())
16 | if expected != string(actual) {
17 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
18 | }
19 | s.Clear()
20 | s.Add(1, 2)
21 |
22 | expected = "[1,2]"
23 | actual, _ = json.Marshal(s.AsSlice())
24 | if expected != string(actual) {
25 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
26 | }
27 | }
28 |
29 | func TestInt32AddUnique(t *testing.T) {
30 |
31 | s := Int32()
32 | s.AddUnique(1)
33 | s.AddUnique(2)
34 | s.AddUnique(2)
35 | s.AddUnique(2)
36 |
37 | expected := "[1,2]"
38 | actual, _ := json.Marshal(s.AsSlice())
39 | if expected != string(actual) {
40 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
41 | }
42 |
43 | s.Clear()
44 | s.AddUnique(1, 2, 1, 2, 2, 1)
45 |
46 | expected = "[1,2]"
47 | actual, _ = json.Marshal(s.AsSlice())
48 | if expected != string(actual) {
49 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
50 | }
51 | }
52 |
53 | func TestInt32AddSlice(t *testing.T) {
54 |
55 | s := Int32()
56 | s.Add(1)
57 | s.Add(2)
58 |
59 | extras := []int32{3, 4}
60 |
61 | s.AddSlice(extras)
62 |
63 | expected := "[1,2,3,4]"
64 | actual, _ := json.Marshal(s.AsSlice())
65 | if expected != string(actual) {
66 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
67 | }
68 | }
69 |
70 | func TestInt32AddSlicer(t *testing.T) {
71 |
72 | s := Int32()
73 | s.Add(1)
74 | s.Add(2)
75 |
76 | p := Int32()
77 | p.Add(3)
78 | p.Add(4)
79 |
80 | s.AddSlicer(p)
81 |
82 | expected := "[1,2,3,4]"
83 | actual, _ := json.Marshal(s.AsSlice())
84 | if expected != string(actual) {
85 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
86 | }
87 | }
88 |
89 | func TestInt32Filter(t *testing.T) {
90 |
91 | s := Int32()
92 | s.Add(18)
93 | s.Add(180)
94 | s.Add(1)
95 | s.Add(10)
96 | s.Add(20)
97 | s.Add(3)
98 | s.Add(29)
99 |
100 | result := s.Filter(func(i int32) bool {
101 | return i > 19
102 | })
103 |
104 | expected := "[180,20,29]"
105 | actual, _ := json.Marshal(result.AsSlice())
106 | if expected != string(actual) {
107 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
108 | }
109 | }
110 |
111 | func TestInt32Each(t *testing.T) {
112 |
113 | s := Int32()
114 | s.Add(18)
115 | s.Add(10)
116 | s.Add(1)
117 | s.Add(10)
118 | s.Add(20)
119 | s.Add(3)
120 | s.Add(29)
121 |
122 | var result int32
123 |
124 | s.Each(func(i int32) {
125 | result = result + i
126 | })
127 |
128 | var expected int32 = 91
129 | if expected != result {
130 | t.Errorf("Expected '%d', but got '%d'", expected, result)
131 | }
132 | }
133 |
134 | // TestOptionalInt32Slice tests when you construct a Int32 with
135 | // an existing slice
136 | func TestOptionalInt32Slice(t *testing.T) {
137 | data := []int32{1, 2, 3}
138 | s := Int32(data)
139 |
140 | var result int32 = 0
141 | s.Each(func(elem int32) {
142 | result += elem
143 | })
144 | var expected int32 = 6
145 | if expected != result {
146 | t.Errorf("Expected '%d', but got '%d'", expected, result)
147 | }
148 | }
149 |
150 | // TestInt32Sort tests that the slicer can be sorted
151 | func TestInt32Sort(t *testing.T) {
152 | data := []int32{5, 4, 3, 2, 1}
153 | s := Int32(data)
154 | s.Sort()
155 | result := s.Join(",")
156 | expected := "1,2,3,4,5"
157 | if expected != result {
158 | t.Errorf("Expected '%s', but got '%s'", expected, result)
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/int64.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Int64Slicer handles slices of int64
10 | type Int64Slicer struct {
11 | slice []int64
12 | }
13 |
14 | // Int64 creates a new Int64Slicer
15 | func Int64(slice ...[]int64) *Int64Slicer {
16 | if len(slice) > 0 {
17 | return &Int64Slicer{slice: slice[0]}
18 | }
19 | return &Int64Slicer{}
20 | }
21 |
22 | // Add a int64 value to the slicer
23 | func (s *Int64Slicer) Add(value int64, additional ...int64) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a int64 value to the slicer if it does not already exist
29 | func (s *Int64Slicer) AddUnique(value int64, additional ...int64) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a int64 slice to the slicer
44 | func (s *Int64Slicer) AddSlice(value []int64) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Int64Slicer) AsSlice() []int64 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Int64Slicer to the slicer
54 | func (s *Int64Slicer) AddSlicer(value *Int64Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Int64Slicer) Filter(fn func(int64) bool) *Int64Slicer {
60 | result := &Int64Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Int64Slicer) Each(fn func(int64)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Int64Slicer) Contains(matcher int64) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Int64Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Int64Slicer) Clear() {
94 | s.slice = []int64{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Int64Slicer) Deduplicate() {
99 |
100 | result := &Int64Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Int64Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Int64Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/int64_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 | )
7 |
8 | func TestInt64Add(t *testing.T) {
9 |
10 | s := Int64()
11 | s.Add(1)
12 | s.Add(2)
13 |
14 | expected := "[1,2]"
15 | actual, _ := json.Marshal(s.AsSlice())
16 | if expected != string(actual) {
17 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
18 | }
19 | s.Clear()
20 | s.Add(1, 2)
21 |
22 | expected = "[1,2]"
23 | actual, _ = json.Marshal(s.AsSlice())
24 | if expected != string(actual) {
25 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
26 | }
27 | }
28 | func TestInt64AddUnique(t *testing.T) {
29 |
30 | s := Int64()
31 | s.AddUnique(1)
32 | s.AddUnique(2)
33 | s.AddUnique(2)
34 | s.AddUnique(2)
35 |
36 | expected := "[1,2]"
37 | actual, _ := json.Marshal(s.AsSlice())
38 | if expected != string(actual) {
39 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
40 | }
41 |
42 | s.Clear()
43 | s.AddUnique(1, 2, 1, 2, 2, 1)
44 |
45 | expected = "[1,2]"
46 | actual, _ = json.Marshal(s.AsSlice())
47 | if expected != string(actual) {
48 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
49 | }
50 | }
51 |
52 | func TestInt64AddSlice(t *testing.T) {
53 |
54 | s := Int64()
55 | s.Add(1)
56 | s.Add(2)
57 |
58 | extras := []int64{3, 4}
59 |
60 | s.AddSlice(extras)
61 |
62 | expected := "[1,2,3,4]"
63 | actual, _ := json.Marshal(s.AsSlice())
64 | if expected != string(actual) {
65 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
66 | }
67 | }
68 |
69 | func TestInt64AddSlicer(t *testing.T) {
70 |
71 | s := Int64()
72 | s.Add(1)
73 | s.Add(2)
74 |
75 | p := Int64()
76 | p.Add(3)
77 | p.Add(4)
78 |
79 | s.AddSlicer(p)
80 |
81 | expected := "[1,2,3,4]"
82 | actual, _ := json.Marshal(s.AsSlice())
83 | if expected != string(actual) {
84 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
85 | }
86 | }
87 |
88 | func TestInt64Filter(t *testing.T) {
89 |
90 | s := Int64()
91 | s.Add(18)
92 | s.Add(180)
93 | s.Add(1)
94 | s.Add(10)
95 | s.Add(20)
96 | s.Add(3)
97 | s.Add(29)
98 |
99 | result := s.Filter(func(i int64) bool {
100 | return i > 19
101 | })
102 |
103 | expected := "[180,20,29]"
104 | actual, _ := json.Marshal(result.AsSlice())
105 | if expected != string(actual) {
106 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
107 | }
108 | }
109 |
110 | func TestInt64Each(t *testing.T) {
111 |
112 | s := Int64()
113 | s.Add(18)
114 | s.Add(10)
115 | s.Add(1)
116 | s.Add(10)
117 | s.Add(20)
118 | s.Add(3)
119 | s.Add(29)
120 |
121 | var result int64
122 |
123 | s.Each(func(i int64) {
124 | result = result + i
125 | })
126 |
127 | var expected int64 = 91
128 | if expected != result {
129 | t.Errorf("Expected '%d', but got '%d'", expected, result)
130 | }
131 | }
132 |
133 | // TestOptionalInt64Slice tests when you construct a Int64 with
134 | // an existing slice
135 | func TestOptionalInt64Slice(t *testing.T) {
136 | data := []int64{1, 2, 3}
137 | s := Int64(data)
138 |
139 | var result int64 = 0
140 | s.Each(func(elem int64) {
141 | result += elem
142 | })
143 | var expected int64 = 6
144 | if expected != result {
145 | t.Errorf("Expected '%d', but got '%d'", expected, result)
146 | }
147 | }
148 |
149 | // TestInt64Sort tests that the slicer can be sorted
150 | func TestInt64Sort(t *testing.T) {
151 | data := []int64{5, 4, 3, 2, 1}
152 | s := Int64(data)
153 | s.Sort()
154 | result := s.Join(",")
155 | expected := "1,2,3,4,5"
156 | if expected != result {
157 | t.Errorf("Expected '%s', but got '%s'", expected, result)
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/int8.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Int8Slicer handles slices of int8
10 | type Int8Slicer struct {
11 | slice []int8
12 | }
13 |
14 | // Int8 creates a new Int8Slicer
15 | func Int8(slice ...[]int8) *Int8Slicer {
16 | if len(slice) > 0 {
17 | return &Int8Slicer{slice: slice[0]}
18 | }
19 | return &Int8Slicer{}
20 | }
21 |
22 | // Add a int8 value to the slicer
23 | func (s *Int8Slicer) Add(value int8, additional ...int8) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a int8 value to the slicer if it does not already exist
29 | func (s *Int8Slicer) AddUnique(value int8, additional ...int8) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a int8 slice to the slicer
44 | func (s *Int8Slicer) AddSlice(value []int8) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Int8Slicer) AsSlice() []int8 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Int8Slicer to the slicer
54 | func (s *Int8Slicer) AddSlicer(value *Int8Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Int8Slicer) Filter(fn func(int8) bool) *Int8Slicer {
60 | result := &Int8Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Int8Slicer) Each(fn func(int8)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Int8Slicer) Contains(matcher int8) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Int8Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Int8Slicer) Clear() {
94 | s.slice = []int8{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Int8Slicer) Deduplicate() {
99 |
100 | result := &Int8Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Int8Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Int8Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/int8_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 | )
7 |
8 | func TestInt8Add(t *testing.T) {
9 |
10 | s := Int8()
11 | s.Add(1)
12 | s.Add(2)
13 |
14 | expected := "[1,2]"
15 | actual, _ := json.Marshal(s.AsSlice())
16 | if expected != string(actual) {
17 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
18 | }
19 | s.Clear()
20 | s.Add(1, 2)
21 |
22 | expected = "[1,2]"
23 | actual, _ = json.Marshal(s.AsSlice())
24 | if expected != string(actual) {
25 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
26 | }
27 | }
28 | func TestInt8AddUnique(t *testing.T) {
29 |
30 | s := Int8()
31 | s.AddUnique(1)
32 | s.AddUnique(2)
33 | s.AddUnique(2)
34 | s.AddUnique(2)
35 |
36 | expected := "[1,2]"
37 | actual, _ := json.Marshal(s.AsSlice())
38 | if expected != string(actual) {
39 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
40 | }
41 |
42 | s.Clear()
43 | s.AddUnique(1, 2, 1, 2, 2, 1)
44 |
45 | expected = "[1,2]"
46 | actual, _ = json.Marshal(s.AsSlice())
47 | if expected != string(actual) {
48 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
49 | }
50 | }
51 | func TestInt8AddSlice(t *testing.T) {
52 |
53 | s := Int8()
54 | s.Add(1)
55 | s.Add(2)
56 |
57 | extras := []int8{3, 4}
58 |
59 | s.AddSlice(extras)
60 |
61 | expected := "[1,2,3,4]"
62 | actual, _ := json.Marshal(s.AsSlice())
63 | if expected != string(actual) {
64 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
65 | }
66 | }
67 |
68 | func TestInt8AddSlicer(t *testing.T) {
69 |
70 | s := Int8()
71 | s.Add(1)
72 | s.Add(2)
73 |
74 | p := Int8()
75 | p.Add(3)
76 | p.Add(4)
77 |
78 | s.AddSlicer(p)
79 |
80 | expected := "[1,2,3,4]"
81 | actual, _ := json.Marshal(s.AsSlice())
82 | if expected != string(actual) {
83 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
84 | }
85 | }
86 | func TestInt8Filter(t *testing.T) {
87 |
88 | s := Int8()
89 | s.Add(18)
90 | s.Add(120)
91 | s.Add(1)
92 | s.Add(10)
93 | s.Add(20)
94 | s.Add(3)
95 | s.Add(29)
96 |
97 | result := s.Filter(func(i int8) bool {
98 | return i > 19
99 | })
100 |
101 | expected := "[120,20,29]"
102 | actual, _ := json.Marshal(result.AsSlice())
103 | if expected != string(actual) {
104 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
105 | }
106 | }
107 |
108 | func TestInt8Each(t *testing.T) {
109 |
110 | s := Int8()
111 | s.Add(18)
112 | s.Add(10)
113 | s.Add(1)
114 | s.Add(10)
115 | s.Add(20)
116 | s.Add(3)
117 | s.Add(29)
118 |
119 | var result int8
120 |
121 | s.Each(func(i int8) {
122 | result = result + i
123 | })
124 |
125 | var expected int8 = 91
126 | if expected != result {
127 | t.Errorf("Expected '%d', but got '%d'", expected, result)
128 | }
129 | }
130 |
131 | // TestOptionalInt8Slice tests when you construct a Int8 with
132 | // an existing slice
133 | func TestOptionalInt8Slice(t *testing.T) {
134 | data := []int8{1, 2, 3}
135 | s := Int8(data)
136 |
137 | var result int8 = 0
138 | s.Each(func(elem int8) {
139 | result += elem
140 | })
141 | var expected int8 = 6
142 | if expected != result {
143 | t.Errorf("Expected '%d', but got '%d'", expected, result)
144 | }
145 | }
146 |
147 | // TestInt8Sort tests that the slicer can be sorted
148 | func TestInt8Sort(t *testing.T) {
149 | data := []int8{5, 4, 3, 2, 1}
150 | s := Int8(data)
151 | s.Sort()
152 | result := s.Join(",")
153 | expected := "1,2,3,4,5"
154 | if expected != result {
155 | t.Errorf("Expected '%s', but got '%s'", expected, result)
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/int_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 | )
7 |
8 | func TestIntAdd(t *testing.T) {
9 |
10 | s := Int()
11 | s.Add(1)
12 | s.Add(2)
13 |
14 | expected := "[1,2]"
15 | actual, _ := json.Marshal(s.AsSlice())
16 | if expected != string(actual) {
17 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
18 | }
19 |
20 | s.Clear()
21 | s.Add(1, 2)
22 |
23 | expected = "[1,2]"
24 | actual, _ = json.Marshal(s.AsSlice())
25 | if expected != string(actual) {
26 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
27 | }
28 | }
29 |
30 | func TestIntAddUnique(t *testing.T) {
31 |
32 | s := Int()
33 | s.AddUnique(1)
34 | s.AddUnique(2)
35 | s.AddUnique(2)
36 | s.AddUnique(2)
37 |
38 | expected := "[1,2]"
39 | actual, _ := json.Marshal(s.AsSlice())
40 | if expected != string(actual) {
41 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
42 | }
43 |
44 | s.Clear()
45 | s.AddUnique(1, 2, 1, 2, 2, 1)
46 |
47 | expected = "[1,2]"
48 | actual, _ = json.Marshal(s.AsSlice())
49 | if expected != string(actual) {
50 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
51 | }
52 | }
53 |
54 | func TestIntAddSlice(t *testing.T) {
55 |
56 | s := Int()
57 | s.Add(1)
58 | s.Add(2)
59 |
60 | extras := []int{3, 4}
61 |
62 | s.AddSlice(extras)
63 |
64 | expected := "[1,2,3,4]"
65 | actual, _ := json.Marshal(s.AsSlice())
66 | if expected != string(actual) {
67 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
68 | }
69 | }
70 |
71 | func TestIntAddSlicer(t *testing.T) {
72 |
73 | s := Int()
74 | s.Add(1)
75 | s.Add(2)
76 |
77 | p := Int()
78 | p.Add(3)
79 | p.Add(4)
80 |
81 | s.AddSlicer(p)
82 |
83 | expected := "[1,2,3,4]"
84 | actual, _ := json.Marshal(s.AsSlice())
85 | if expected != string(actual) {
86 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
87 | }
88 | }
89 |
90 | func TestIntFilter(t *testing.T) {
91 |
92 | s := Int()
93 | s.Add(18)
94 | s.Add(120)
95 | s.Add(1)
96 | s.Add(10)
97 | s.Add(20)
98 | s.Add(3)
99 | s.Add(29)
100 |
101 | result := s.Filter(func(i int) bool {
102 | return i > 19
103 | })
104 |
105 | expected := "[120,20,29]"
106 | actual, _ := json.Marshal(result.AsSlice())
107 | if expected != string(actual) {
108 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
109 | }
110 | }
111 |
112 | // TestOptionalIntSlice tests when you construct a Int with
113 | // an existing slice
114 | func TestOptionalIntSlice(t *testing.T) {
115 | data := []int{1, 2, 3}
116 | s := Int(data)
117 |
118 | var result = 0
119 | s.Each(func(elem int) {
120 | result += elem
121 | })
122 | var expected = 6
123 | if expected != result {
124 | t.Errorf("Expected '%d', but got '%d'", expected, result)
125 | }
126 | }
127 |
128 | // TestIntSort tests that the slicer can be sorted
129 | func TestIntSort(t *testing.T) {
130 | data := []int{5, 4, 3, 2, 1}
131 | s := Int(data)
132 | s.Sort()
133 | result := s.Join(",")
134 | expected := "1,2,3,4,5"
135 | if expected != result {
136 | t.Errorf("Expected '%s', but got '%s'", expected, result)
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/interface.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "fmt"
6 | import "strings"
7 |
8 | // InterfaceSlicer handles slices of interface{}
9 | type InterfaceSlicer struct {
10 | slice []interface{}
11 | }
12 |
13 | // Interface creates a new InterfaceSlicer
14 | func Interface(slice ...[]interface{}) *InterfaceSlicer {
15 | if len(slice) > 0 {
16 | return &InterfaceSlicer{slice: slice[0]}
17 | }
18 | return &InterfaceSlicer{}
19 | }
20 |
21 | // Add a interface{} value to the slicer
22 | func (s *InterfaceSlicer) Add(value interface{}, additional ...interface{}) {
23 | s.slice = append(s.slice, value)
24 | s.slice = append(s.slice, additional...)
25 | }
26 |
27 | // AddUnique adds a interface{} value to the slicer if it does not already exist
28 | func (s *InterfaceSlicer) AddUnique(value interface{}, additional ...interface{}) {
29 |
30 | if !s.Contains(value) {
31 | s.slice = append(s.slice, value)
32 | }
33 |
34 | // Add additional values
35 | for _, value := range additional {
36 | if !s.Contains(value) {
37 | s.slice = append(s.slice, value)
38 | }
39 | }
40 | }
41 |
42 | // AddSlice adds a interface{} slice to the slicer
43 | func (s *InterfaceSlicer) AddSlice(value []interface{}) {
44 | s.slice = append(s.slice, value...)
45 | }
46 |
47 | // AsSlice returns the slice
48 | func (s *InterfaceSlicer) AsSlice() []interface{} {
49 | return s.slice
50 | }
51 |
52 | // AddSlicer appends a InterfaceSlicer to the slicer
53 | func (s *InterfaceSlicer) AddSlicer(value *InterfaceSlicer) {
54 | s.slice = append(s.slice, value.AsSlice()...)
55 | }
56 |
57 | // Filter the slice based on the given function
58 | func (s *InterfaceSlicer) Filter(fn func(interface{}) bool) *InterfaceSlicer {
59 | result := &InterfaceSlicer{}
60 | for _, elem := range s.slice {
61 | if fn(elem) {
62 | result.Add(elem)
63 | }
64 | }
65 | return result
66 | }
67 |
68 | // Each runs a function on every element of the slice
69 | func (s *InterfaceSlicer) Each(fn func(interface{})) {
70 | for _, elem := range s.slice {
71 | fn(elem)
72 | }
73 | }
74 |
75 | // Contains indicates if the given value is in the slice
76 | func (s *InterfaceSlicer) Contains(matcher interface{}) bool {
77 | result := false
78 | for _, elem := range s.slice {
79 | if elem == matcher {
80 | result = true
81 | }
82 | }
83 | return result
84 | }
85 |
86 | // Length returns the number of elements in the slice
87 | func (s *InterfaceSlicer) Length() int {
88 | return len(s.slice)
89 | }
90 |
91 | // Clear all elements in the slice
92 | func (s *InterfaceSlicer) Clear() {
93 | s.slice = []interface{}{}
94 | }
95 |
96 | // Deduplicate removes duplicate values from the slice
97 | func (s *InterfaceSlicer) Deduplicate() {
98 |
99 | result := &InterfaceSlicer{}
100 |
101 | for _, elem := range s.slice {
102 | if !result.Contains(elem) {
103 | result.Add(elem)
104 | }
105 | }
106 |
107 | s.slice = result.AsSlice()
108 | }
109 |
110 | // Join returns a string with the slicer elements separated by the given separator
111 | func (s *InterfaceSlicer) Join(separator string) string {
112 | var builder strings.Builder
113 |
114 | // Shortcut no elements
115 | if len(s.slice) == 0 {
116 | return ""
117 | }
118 |
119 | // Iterate over length - 1
120 | index := 0
121 | for index = 0; index < len(s.slice)-1; index++ {
122 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
123 | }
124 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
125 | result := builder.String()
126 | return result
127 | }
128 |
--------------------------------------------------------------------------------
/interface_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 | )
7 |
8 | func TestInterfaceAdd(t *testing.T) {
9 |
10 | s := Interface()
11 | var a interface{} = 1
12 | var b interface{} = "hello"
13 | s.Add(a)
14 | s.Add(b)
15 |
16 | expected := `[1,"hello"]`
17 | actual, _ := json.Marshal(s.AsSlice())
18 | if expected != string(actual) {
19 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
20 | }
21 |
22 | // Add more than one value
23 | s.Clear()
24 | s.Add(a, b)
25 | expected = `[1,"hello"]`
26 | actual, _ = json.Marshal(s.AsSlice())
27 | if expected != string(actual) {
28 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
29 | }
30 | }
31 |
32 | func TestInterfaceAddUnique(t *testing.T) {
33 |
34 | s := Interface()
35 | var a interface{} = 1
36 | var b interface{} = "hello"
37 | s.AddUnique(a)
38 | s.AddUnique(a)
39 | s.AddUnique(b)
40 |
41 | expected := `[1,"hello"]`
42 | actual, _ := json.Marshal(s.AsSlice())
43 | if expected != string(actual) {
44 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
45 | }
46 |
47 | // AddUnique more than one value
48 | s.Clear()
49 | s.AddUnique(a, b, b, a)
50 | expected = `[1,"hello"]`
51 | actual, _ = json.Marshal(s.AsSlice())
52 | if expected != string(actual) {
53 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
54 | }
55 | }
56 |
57 | func TestInterfaceAddSlice(t *testing.T) {
58 |
59 | s := Interface()
60 | var a interface{} = 1
61 | var b interface{} = "hello"
62 | s.Add(a)
63 | s.Add(b)
64 |
65 | extras := []interface{}{true, 6.6}
66 |
67 | s.AddSlice(extras)
68 |
69 | expected := `[1,"hello",true,6.6]`
70 | actual, _ := json.Marshal(s.AsSlice())
71 | if expected != string(actual) {
72 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
73 | }
74 | }
75 | func TestInterfaceAddSlicer(t *testing.T) {
76 |
77 | s := Interface()
78 | var a interface{} = 1
79 | var b interface{} = "hello"
80 | s.Add(a)
81 | s.Add(b)
82 |
83 | p := Interface()
84 | var c interface{} = true
85 | var d interface{} = 6.6
86 | p.Add(c)
87 | p.Add(d)
88 |
89 | s.AddSlicer(p)
90 |
91 | expected := `[1,"hello",true,6.6]`
92 | actual, _ := json.Marshal(s.AsSlice())
93 | if expected != string(actual) {
94 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
95 | }
96 | }
97 |
98 | func TestInterfaceFilter(t *testing.T) {
99 |
100 | s := Interface()
101 | s.Add(1)
102 | s.Add("hello")
103 | s.Add(true)
104 | s.Add("world")
105 | s.Add(9.9)
106 |
107 | result := s.Filter(func(i interface{}) bool {
108 | _, ok := i.(string)
109 | return ok
110 | })
111 |
112 | expected := `["hello","world"]`
113 | actual, _ := json.Marshal(result.AsSlice())
114 | if expected != string(actual) {
115 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
116 | }
117 | }
118 |
119 | func TestInterfaceEach(t *testing.T) {
120 |
121 | s := Interface()
122 | s.Add(1)
123 | s.Add("hello")
124 | s.Add(true)
125 | s.Add("world")
126 | s.Add(9.9)
127 |
128 | result := String()
129 | s.Each(func(i interface{}) {
130 | val, ok := i.(string)
131 | if ok {
132 | result.Add(val + "!")
133 | }
134 | })
135 |
136 | expected := `["hello!","world!"]`
137 | actual, _ := json.Marshal(result.AsSlice())
138 | if expected != string(actual) {
139 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
140 | }
141 | }
142 |
143 | // TestOptionalInterfaceSlice tests when you construct a Interface with
144 | // an existing slice
145 | func TestOptionalInterfaceSlice(t *testing.T) {
146 | data := []interface{}{"one", "two", "three"}
147 | s := Interface(data)
148 |
149 | result := ""
150 | s.Each(func(elem interface{}) {
151 | result += elem.(string)
152 | })
153 | expected := "onetwothree"
154 | if expected != result {
155 | t.Errorf("Expected '%s', but got '%s'", expected, result)
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/join_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import "testing"
4 |
5 | func TestStringJoin(t *testing.T) {
6 |
7 | /* Test multiple elements */
8 | data := []string{"cat", "bat", "dog", "arachnid"}
9 | s := String(data)
10 |
11 | // Positive test
12 | expected := "cat,bat,dog,arachnid"
13 | result := s.Join(",")
14 | if result != expected {
15 | t.Errorf("Expected '%s', but got '%s'", expected, result)
16 | }
17 |
18 | // Negative test
19 | expected = "cat,bat,dog,horse"
20 | result = s.Join(",")
21 | if result == expected {
22 | t.Errorf("Expected '%s', but got '%s'", expected, result)
23 | }
24 | /* Test single element */
25 | s = String()
26 | s.Add("hello")
27 |
28 | // Positive test
29 | expected = "hello"
30 | result = s.Join(",")
31 | if result != expected {
32 | t.Errorf("Expected '%s', but got '%s'", expected, result)
33 | }
34 |
35 | // Negative test
36 | expected = "hello,"
37 | result = s.Join(",")
38 | if result == expected {
39 | t.Errorf("Expected '%s', but got '%s'", expected, result)
40 | }
41 |
42 | /* Test no element */
43 | s = String()
44 | expected = ""
45 | result = s.Join(",")
46 | if result != expected {
47 | t.Errorf("Expected '%s', but got '%s'", expected, result)
48 | }
49 | }
50 |
51 | func TestInterfaceJoin(t *testing.T) {
52 |
53 | /* Test multiple elements */
54 | s := Interface()
55 | var a interface{} = 1
56 | var b interface{} = "hello"
57 | s.Add(a)
58 | s.Add(b)
59 |
60 | // Positive test
61 | expected := "1,hello"
62 | result := s.Join(",")
63 | if result != expected {
64 | t.Errorf("Expected '%s', but got '%s'", expected, result)
65 | }
66 |
67 | // Negative test
68 | expected = "1,hello,"
69 | result = s.Join(",")
70 | if result == expected {
71 | t.Errorf("Expected '%s', but got '%s'", expected, result)
72 | }
73 |
74 | /* Test single element */
75 | s = Interface()
76 | s.Add(a)
77 |
78 | // Positive test
79 | expected = "1"
80 | result = s.Join(",")
81 | if result != expected {
82 | t.Errorf("Expected '%s', but got '%s'", expected, result)
83 | }
84 |
85 | // Negative test
86 | expected = "1,"
87 | result = s.Join(",")
88 | if result == expected {
89 | t.Errorf("Expected '%s', but got '%s'", expected, result)
90 | }
91 |
92 | /* Test no element */
93 | s = Interface()
94 | expected = ""
95 | result = s.Join(",")
96 | if result != expected {
97 | t.Errorf("Expected '%s', but got '%s'", expected, result)
98 | }
99 |
100 | }
101 |
102 | func TestInt64Join(t *testing.T) {
103 |
104 | /* Test multiple elements */
105 |
106 | data := []int64{1, 2, 3}
107 | s := Int64(data)
108 |
109 | // Positive test
110 | expected := "1,2,3"
111 | result := s.Join(",")
112 | if result != expected {
113 | t.Errorf("Expected '%s', but got '%s'", expected, result)
114 | }
115 |
116 | // Negative test
117 | expected = "1,2,3,"
118 | result = s.Join(",")
119 | if result == expected {
120 | t.Errorf("Expected '%s', but got '%s'", expected, result)
121 | }
122 |
123 | /* Test single element */
124 | s = Int64()
125 | s.Add(1)
126 |
127 | // Positive test
128 | expected = "1"
129 | result = s.Join(",")
130 | if result != expected {
131 | t.Errorf("Expected '%s', but got '%s'", expected, result)
132 | }
133 |
134 | // Negative test
135 | expected = "1,"
136 | result = s.Join(",")
137 | if result == expected {
138 | t.Errorf("Expected '%s', but got '%s'", expected, result)
139 | }
140 |
141 | /* Test no element */
142 | s = Int64()
143 | expected = ""
144 | result = s.Join(",")
145 | if result != expected {
146 | t.Errorf("Expected '%s', but got '%s'", expected, result)
147 | }
148 | }
149 |
150 | func TestInt32Join(t *testing.T) {
151 |
152 | /* Test multiple elements */
153 |
154 | data := []int32{1, 2, 3}
155 | s := Int32(data)
156 |
157 | // Positive test
158 | expected := "1,2,3"
159 | result := s.Join(",")
160 | if result != expected {
161 | t.Errorf("Expected '%s', but got '%s'", expected, result)
162 | }
163 |
164 | // Negative test
165 | expected = "1,2,3,"
166 | result = s.Join(",")
167 | if result == expected {
168 | t.Errorf("Expected '%s', but got '%s'", expected, result)
169 | }
170 |
171 | /* Test single element */
172 | s = Int32()
173 | s.Add(1)
174 |
175 | // Positive test
176 | expected = "1"
177 | result = s.Join(",")
178 | if result != expected {
179 | t.Errorf("Expected '%s', but got '%s'", expected, result)
180 | }
181 |
182 | // Negative test
183 | expected = "1,"
184 | result = s.Join(",")
185 | if result == expected {
186 | t.Errorf("Expected '%s', but got '%s'", expected, result)
187 | }
188 |
189 | /* Test no element */
190 | s = Int32()
191 | expected = ""
192 | result = s.Join(",")
193 | if result != expected {
194 | t.Errorf("Expected '%s', but got '%s'", expected, result)
195 | }
196 | }
197 |
198 | func TestInt16Join(t *testing.T) {
199 |
200 | /* Test multiple elements */
201 |
202 | data := []int16{1, 2, 3}
203 | s := Int16(data)
204 |
205 | // Positive test
206 | expected := "1,2,3"
207 | result := s.Join(",")
208 | if result != expected {
209 | t.Errorf("Expected '%s', but got '%s'", expected, result)
210 | }
211 |
212 | // Negative test
213 | expected = "1,2,3,"
214 | result = s.Join(",")
215 | if result == expected {
216 | t.Errorf("Expected '%s', but got '%s'", expected, result)
217 | }
218 |
219 | /* Test single element */
220 | s = Int16()
221 | s.Add(1)
222 |
223 | // Positive test
224 | expected = "1"
225 | result = s.Join(",")
226 | if result != expected {
227 | t.Errorf("Expected '%s', but got '%s'", expected, result)
228 | }
229 |
230 | // Negative test
231 | expected = "1,"
232 | result = s.Join(",")
233 | if result == expected {
234 | t.Errorf("Expected '%s', but got '%s'", expected, result)
235 | }
236 |
237 | /* Test no element */
238 | s = Int16()
239 | expected = ""
240 | result = s.Join(",")
241 | if result != expected {
242 | t.Errorf("Expected '%s', but got '%s'", expected, result)
243 | }
244 | }
245 |
246 | func TestInt8Join(t *testing.T) {
247 |
248 | /* Test multiple elements */
249 |
250 | data := []int8{1, 2, 3}
251 | s := Int8(data)
252 |
253 | // Positive test
254 | expected := "1,2,3"
255 | result := s.Join(",")
256 | if result != expected {
257 | t.Errorf("Expected '%s', but got '%s'", expected, result)
258 | }
259 |
260 | // Negative test
261 | expected = "1,2,3,"
262 | result = s.Join(",")
263 | if result == expected {
264 | t.Errorf("Expected '%s', but got '%s'", expected, result)
265 | }
266 |
267 | /* Test single element */
268 | s = Int8()
269 | s.Add(1)
270 |
271 | // Positive test
272 | expected = "1"
273 | result = s.Join(",")
274 | if result != expected {
275 | t.Errorf("Expected '%s', but got '%s'", expected, result)
276 | }
277 |
278 | // Negative test
279 | expected = "1,"
280 | result = s.Join(",")
281 | if result == expected {
282 | t.Errorf("Expected '%s', but got '%s'", expected, result)
283 | }
284 |
285 | /* Test no element */
286 | s = Int8()
287 | expected = ""
288 | result = s.Join(",")
289 | if result != expected {
290 | t.Errorf("Expected '%s', but got '%s'", expected, result)
291 | }
292 | }
293 |
294 | func TestIntJoin(t *testing.T) {
295 |
296 | /* Test multiple elements */
297 |
298 | data := []int{1, 2, 3}
299 | s := Int(data)
300 |
301 | // Positive test
302 | expected := "1,2,3"
303 | result := s.Join(",")
304 | if result != expected {
305 | t.Errorf("Expected '%s', but got '%s'", expected, result)
306 | }
307 |
308 | // Negative test
309 | expected = "1,2,3,"
310 | result = s.Join(",")
311 | if result == expected {
312 | t.Errorf("Expected '%s', but got '%s'", expected, result)
313 | }
314 |
315 | /* Test single element */
316 | s = Int()
317 | s.Add(1)
318 |
319 | // Positive test
320 | expected = "1"
321 | result = s.Join(",")
322 | if result != expected {
323 | t.Errorf("Expected '%s', but got '%s'", expected, result)
324 | }
325 |
326 | // Negative test
327 | expected = "1,"
328 | result = s.Join(",")
329 | if result == expected {
330 | t.Errorf("Expected '%s', but got '%s'", expected, result)
331 | }
332 |
333 | /* Test no element */
334 | s = Int()
335 | expected = ""
336 | result = s.Join(",")
337 | if result != expected {
338 | t.Errorf("Expected '%s', but got '%s'", expected, result)
339 | }
340 | }
341 |
342 | func TestBoolJoin(t *testing.T) {
343 |
344 | /* Test multpile elements */
345 | data := []bool{true, false, true}
346 | s := Bool(data)
347 |
348 | // Positive test
349 | expected := "true,false,true"
350 | result := s.Join(",")
351 | if result != expected {
352 | t.Errorf("Expected '%s', but got '%s'", expected, result)
353 | }
354 |
355 | // Negative test
356 | expected = "true,false,true,"
357 | result = s.Join(",")
358 | if result == expected {
359 | t.Errorf("Expected '%s', but got '%s'", expected, result)
360 | }
361 | /* Test single element */
362 | s = Bool()
363 | s.Add(false)
364 |
365 | // Positive test
366 | expected = "false"
367 | result = s.Join(",")
368 | if result != expected {
369 | t.Errorf("Expected '%s', but got '%s'", expected, result)
370 | }
371 |
372 | // Negative test
373 | expected = "false,"
374 | result = s.Join(",")
375 | if result == expected {
376 | t.Errorf("Expected '%s', but got '%s'", expected, result)
377 | }
378 |
379 | /* Test no element */
380 | s = Bool()
381 | expected = ""
382 | result = s.Join(",")
383 | if result != expected {
384 | t.Errorf("Expected '%s', but got '%s'", expected, result)
385 | }
386 | }
387 |
388 | func TestFloat64Join(t *testing.T) {
389 |
390 | data := []float64{1.4, 2.1, 3}
391 | s := Float64(data)
392 |
393 | // Positive test
394 | expected := "1.4,2.1,3"
395 | result := s.Join(",")
396 | if result != expected {
397 | t.Errorf("Expected '%s', but got '%s'", expected, result)
398 | }
399 |
400 | // Negative test
401 | expected = "1.4,2.1,3,"
402 | result = s.Join(",")
403 | if result == expected {
404 | t.Errorf("Expected '%s', but got '%s'", expected, result)
405 | }
406 | /* Test single element */
407 | s = Float64()
408 | s.Add(1.982)
409 |
410 | // Positive test
411 | expected = "1.982"
412 | result = s.Join(",")
413 | if result != expected {
414 | t.Errorf("Expected '%s', but got '%s'", expected, result)
415 | }
416 |
417 | // Negative test
418 | expected = "1.982,"
419 | result = s.Join(",")
420 | if result == expected {
421 | t.Errorf("Expected '%s', but got '%s'", expected, result)
422 | }
423 |
424 | /* Test no element */
425 | s = Float64()
426 | expected = ""
427 | result = s.Join(",")
428 | if result != expected {
429 | t.Errorf("Expected '%s', but got '%s'", expected, result)
430 | }
431 | }
432 | func TestFloat32Join(t *testing.T) {
433 |
434 | data := []float32{1.4, 2.1, 3}
435 | s := Float32(data)
436 |
437 | // Positive test
438 | expected := "1.4,2.1,3"
439 | result := s.Join(",")
440 | if result != expected {
441 | t.Errorf("Expected '%s', but got '%s'", expected, result)
442 | }
443 |
444 | // Negative test
445 | expected = "1.4,2.1,3,"
446 | result = s.Join(",")
447 | if result == expected {
448 | t.Errorf("Expected '%s', but got '%s'", expected, result)
449 | }
450 |
451 | /* Test single element */
452 | s = Float32()
453 | s.Add(1.982)
454 |
455 | // Positive test
456 | expected = "1.982"
457 | result = s.Join(",")
458 | if result != expected {
459 | t.Errorf("Expected '%s', but got '%s'", expected, result)
460 | }
461 |
462 | // Negative test
463 | expected = "1.982,"
464 | result = s.Join(",")
465 | if result == expected {
466 | t.Errorf("Expected '%s', but got '%s'", expected, result)
467 | }
468 |
469 | /* Test no element */
470 | s = Float32()
471 | expected = ""
472 | result = s.Join(",")
473 | if result != expected {
474 | t.Errorf("Expected '%s', but got '%s'", expected, result)
475 | }
476 | }
477 |
--------------------------------------------------------------------------------
/length_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import "testing"
4 |
5 | func TestStringLength(t *testing.T) {
6 |
7 | /* Test multiple elements */
8 | data := []string{"cat", "bat", "dog", "arachnid"}
9 | s := String(data)
10 |
11 | // Positive test
12 | expected := 4
13 | result := s.Length()
14 | if result != expected {
15 | t.Errorf("Expected '%d', but got '%d'", expected, result)
16 | }
17 |
18 | // Negative test
19 | expected = 3
20 | result = s.Length()
21 | if result == expected {
22 | t.Errorf("Expected '%d', but got '%d'", expected, result)
23 | }
24 |
25 | /* Test no element */
26 | s = String()
27 | expected = 0
28 | result = s.Length()
29 | if result != expected {
30 | t.Errorf("Expected '%d', but got '%d'", expected, result)
31 | }
32 | }
33 |
34 | func TestInterfaceLength(t *testing.T) {
35 |
36 | /* Test multiple elements */
37 | s := Interface()
38 | var a interface{} = 1
39 | var b interface{} = "hello"
40 | s.Add(a)
41 | s.Add(b)
42 |
43 | // Positive test
44 | expected := 2
45 | result := s.Length()
46 | if result != expected {
47 | t.Errorf("Expected '%d', but got '%d'", expected, result)
48 | }
49 |
50 | // Negative test
51 | expected = 3
52 | result = s.Length()
53 | if result == expected {
54 | t.Errorf("Expected '%d', but got '%d'", expected, result)
55 | }
56 |
57 | /* Test no element */
58 | s = Interface()
59 | expected = 0
60 | result = s.Length()
61 | if result != expected {
62 | t.Errorf("Expected '%d', but got '%d'", expected, result)
63 | }
64 |
65 | }
66 |
67 | func TestInt64Length(t *testing.T) {
68 |
69 | /* Test multiple elements */
70 |
71 | data := []int64{1, 2, 3}
72 | s := Int64(data)
73 |
74 | // Positive test
75 | expected := 3
76 | result := s.Length()
77 | if result != expected {
78 | t.Errorf("Expected '%d', but got '%d'", expected, result)
79 | }
80 |
81 | // Negative test
82 | expected = 2
83 | result = s.Length()
84 | if result == expected {
85 | t.Errorf("Expected '%d', but got '%d'", expected, result)
86 | }
87 |
88 | /* Test no element */
89 | s = Int64()
90 | expected = 0
91 | result = s.Length()
92 | if result != expected {
93 | t.Errorf("Expected '%d', but got '%d'", expected, result)
94 | }
95 | }
96 |
97 | func TestInt32Length(t *testing.T) {
98 |
99 | /* Test multiple elements */
100 |
101 | data := []int32{1, 2, 3}
102 | s := Int32(data)
103 |
104 | // Positive test
105 | expected := 3
106 | result := s.Length()
107 | if result != expected {
108 | t.Errorf("Expected '%d', but got '%d'", expected, result)
109 | }
110 |
111 | // Negative test
112 | expected = 2
113 | result = s.Length()
114 | if result == expected {
115 | t.Errorf("Expected '%d', but got '%d'", expected, result)
116 | }
117 |
118 | /* Test no element */
119 | s = Int32()
120 | expected = 0
121 | result = s.Length()
122 | if result != expected {
123 | t.Errorf("Expected '%d', but got '%d'", expected, result)
124 | }
125 | }
126 |
127 | func TestInt16Length(t *testing.T) {
128 |
129 | /* Test multiple elements */
130 |
131 | data := []int16{1, 2, 3}
132 | s := Int16(data)
133 |
134 | // Positive test
135 | expected := 3
136 | result := s.Length()
137 | if result != expected {
138 | t.Errorf("Expected '%d', but got '%d'", expected, result)
139 | }
140 |
141 | // Negative test
142 | expected = 2
143 | result = s.Length()
144 | if result == expected {
145 | t.Errorf("Expected '%d', but got '%d'", expected, result)
146 | }
147 |
148 | /* Test no element */
149 | s = Int16()
150 | expected = 0
151 | result = s.Length()
152 | if result != expected {
153 | t.Errorf("Expected '%d', but got '%d'", expected, result)
154 | }
155 | }
156 |
157 | func TestInt8Length(t *testing.T) {
158 |
159 | /* Test multiple elements */
160 |
161 | data := []int8{1, 2, 3}
162 | s := Int8(data)
163 |
164 | // Positive test
165 | expected := 3
166 | result := s.Length()
167 | if result != expected {
168 | t.Errorf("Expected '%d', but got '%d'", expected, result)
169 | }
170 |
171 | // Negative test
172 | expected = 2
173 | result = s.Length()
174 | if result == expected {
175 | t.Errorf("Expected '%d', but got '%d'", expected, result)
176 | }
177 |
178 | /* Test no element */
179 | s = Int8()
180 | expected = 0
181 | result = s.Length()
182 | if result != expected {
183 | t.Errorf("Expected '%d', but got '%d'", expected, result)
184 | }
185 | }
186 |
187 | func TestIntLength(t *testing.T) {
188 |
189 | /* Test multiple elements */
190 |
191 | data := []int{1, 2, 3}
192 | s := Int(data)
193 |
194 | // Positive test
195 | expected := 3
196 | result := s.Length()
197 | if result != expected {
198 | t.Errorf("Expected '%d', but got '%d'", expected, result)
199 | }
200 |
201 | // Negative test
202 | expected = 2
203 | result = s.Length()
204 | if result == expected {
205 | t.Errorf("Expected '%d', but got '%d'", expected, result)
206 | }
207 |
208 | /* Test no element */
209 | s = Int()
210 | expected = 0
211 | result = s.Length()
212 | if result != expected {
213 | t.Errorf("Expected '%d', but got '%d'", expected, result)
214 | }
215 | }
216 |
217 | func TestBoolLength(t *testing.T) {
218 |
219 | /* Test multpile elements */
220 | data := []bool{true, false, true}
221 | s := Bool(data)
222 |
223 | // Positive test
224 | expected := 3
225 | result := s.Length()
226 | if result != expected {
227 | t.Errorf("Expected '%d', but got '%d'", expected, result)
228 | }
229 |
230 | // Negative test
231 | expected = 2
232 | result = s.Length()
233 | if result == expected {
234 | t.Errorf("Expected '%d', but got '%d'", expected, result)
235 | }
236 |
237 | /* Test no element */
238 | s = Bool()
239 | expected = 0
240 | result = s.Length()
241 | if result != expected {
242 | t.Errorf("Expected '%d', but got '%d'", expected, result)
243 | }
244 | }
245 |
246 | func TestFloat64Length(t *testing.T) {
247 |
248 | data := []float64{1.4, 2.1, 3}
249 | s := Float64(data)
250 |
251 | // Positive test
252 | expected := 3
253 | result := s.Length()
254 | if result != expected {
255 | t.Errorf("Expected '%d', but got '%d'", expected, result)
256 | }
257 |
258 | // Negative test
259 | expected = 2
260 | result = s.Length()
261 | if result == expected {
262 | t.Errorf("Expected '%d', but got '%d'", expected, result)
263 | }
264 |
265 | /* Test no element */
266 | s = Float64()
267 | expected = 0
268 | result = s.Length()
269 | if result != expected {
270 | t.Errorf("Expected '%d', but got '%d'", expected, result)
271 | }
272 | }
273 | func TestFloat32Length(t *testing.T) {
274 |
275 | data := []float32{1.4, 2.1, 3}
276 | s := Float32(data)
277 |
278 | // Positive test
279 | expected := 3
280 | result := s.Length()
281 | if result != expected {
282 | t.Errorf("Expected '%d', but got '%d'", expected, result)
283 | }
284 |
285 | // Negative test
286 | expected = 2
287 | result = s.Length()
288 | if result == expected {
289 | t.Errorf("Expected '%d', but got '%d'", expected, result)
290 | }
291 |
292 | /* Test no element */
293 | s = Float32()
294 | expected = 0
295 | result = s.Length()
296 | if result != expected {
297 | t.Errorf("Expected '%d', but got '%d'", expected, result)
298 | }
299 | }
300 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leaanthony/slicer/33c619aa00508e2307b8ed4038d202e200240476/logo.png
--------------------------------------------------------------------------------
/scripts/generate.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "os"
7 | "path/filepath"
8 | "strings"
9 | )
10 |
11 | func main() {
12 | types := []string{"string", "int64", "int32", "int16", "int8", "int", "uint64", "uint32", "uint16", "uint8", "uint", "float64", "float32", "bool", "interface"}
13 |
14 | // Read template
15 | cwd, err := os.Getwd()
16 | if err != nil {
17 | panic(err)
18 | }
19 |
20 | for _, t := range types {
21 | bytes, err := ioutil.ReadFile(filepath.Join(cwd, "slicer.template"))
22 | if err != nil {
23 | panic(err)
24 | }
25 | template := string(bytes)
26 | thisTemplate := template
27 | Type := t
28 | TypeTitle := strings.Title(t)
29 |
30 | if Type == "interface" {
31 | Type = "interface{}"
32 | }
33 | SlicerName := TypeTitle + "Slicer"
34 |
35 | // Type specific additions
36 | thisTemplate = fixup(thisTemplate, t)
37 |
38 | // Replace type
39 | thisTemplate = strings.ReplaceAll(thisTemplate, "_TYPE_", Type)
40 | thisTemplate = strings.ReplaceAll(thisTemplate, "_TYPETITLE_", TypeTitle)
41 | thisTemplate = strings.ReplaceAll(thisTemplate, "_SLICERNAME_", SlicerName)
42 |
43 | // Save file
44 | targetFile := filepath.Join(cwd, "..", t+".go")
45 | err = ioutil.WriteFile(targetFile, []byte(thisTemplate), 0644)
46 | if err != nil {
47 | panic(err)
48 | }
49 | }
50 |
51 | }
52 |
53 | func fixup(template string, t string) string {
54 |
55 | template = fixupJoin(template, t)
56 | template = fixupSort(template, t)
57 |
58 | return template
59 | }
60 |
61 | func fixupSort(template string, t string) string {
62 | // Sort String
63 | sortString := `
64 | // Sort the slice values
65 | func (s *StringSlicer) Sort() {
66 | sort.Strings(s.slice)
67 | }
68 | `
69 | sortDefault := `
70 | // Sort the slice values
71 | func (s *_SLICERNAME_) Sort() {
72 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
73 | }`
74 |
75 | switch t {
76 | case "string":
77 | template += sortString
78 | template = addImport(template, "sort")
79 | case "interface", "bool": //Ignore
80 | default:
81 | template += sortDefault
82 | template = addImport(template, "sort")
83 | }
84 | return template
85 | }
86 |
87 | func fixupJoin(template string, t string) string {
88 |
89 | //Join
90 | joinGeneric := `
91 | // Join returns a string with the slicer elements separated by the given separator
92 | func (s *_SLICERNAME_) Join(separator string) string {
93 | var builder strings.Builder
94 |
95 | // Shortcut no elements
96 | if len(s.slice) == 0 {
97 | return ""
98 | }
99 |
100 | // Iterate over length - 1
101 | index := 0
102 | for index = 0; index < len(s.slice)-1; index++ {
103 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
104 | }
105 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
106 | result := builder.String()
107 | return result
108 | }`
109 | joinString := `
110 | // Join returns a string with the slicer elements separated by the given separator
111 | func (s *StringSlicer) Join(separator string) string {
112 | return strings.Join(s.slice, separator)
113 | }`
114 |
115 | switch t {
116 | case "string":
117 | template += joinString
118 | // template = addImport(template, "sort")
119 | default:
120 | template += joinGeneric
121 | template = addImport(template, "fmt")
122 | }
123 | return template
124 | }
125 |
126 | func addImport(template string, name string) string {
127 | newText := fmt.Sprintf("// Imports\nimport \"%s\"", name)
128 | return strings.ReplaceAll(template, "// Imports", newText)
129 | }
130 |
--------------------------------------------------------------------------------
/scripts/slicer.template:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "strings"
6 |
7 | // _SLICERNAME_ handles slices of _TYPE_
8 | type _SLICERNAME_ struct {
9 | slice []_TYPE_
10 | }
11 |
12 | // _TYPETITLE_ creates a new _SLICERNAME_
13 | func _TYPETITLE_(slice ...[]_TYPE_) *_SLICERNAME_ {
14 | if len(slice) > 0 {
15 | return &_SLICERNAME_{slice: slice[0]}
16 | }
17 | return &_SLICERNAME_{}
18 | }
19 |
20 | // Add a _TYPE_ value to the slicer
21 | func (s *_SLICERNAME_) Add(value _TYPE_, additional ..._TYPE_) {
22 | s.slice = append(s.slice, value)
23 | s.slice = append(s.slice, additional...)
24 | }
25 |
26 | // AddUnique adds a _TYPE_ value to the slicer if it does not already exist
27 | func (s *_SLICERNAME_) AddUnique(value _TYPE_, additional ..._TYPE_) {
28 |
29 | if !s.Contains(value) {
30 | s.slice = append(s.slice, value)
31 | }
32 |
33 | // Add additional values
34 | for _, value := range additional {
35 | if !s.Contains(value) {
36 | s.slice = append(s.slice, value)
37 | }
38 | }
39 | }
40 |
41 | // AddSlice adds a _TYPE_ slice to the slicer
42 | func (s *_SLICERNAME_) AddSlice(value []_TYPE_) {
43 | s.slice = append(s.slice, value...)
44 | }
45 |
46 | // AsSlice returns the slice
47 | func (s *_SLICERNAME_) AsSlice() []_TYPE_ {
48 | return s.slice
49 | }
50 |
51 | // AddSlicer appends a _SLICERNAME_ to the slicer
52 | func (s *_SLICERNAME_) AddSlicer(value *_SLICERNAME_) {
53 | s.slice = append(s.slice, value.AsSlice()...)
54 | }
55 |
56 | // Filter the slice based on the given function
57 | func (s *_SLICERNAME_) Filter(fn func(_TYPE_) bool) *_SLICERNAME_ {
58 | result := &_SLICERNAME_{}
59 | for _, elem := range s.slice {
60 | if fn(elem) {
61 | result.Add(elem)
62 | }
63 | }
64 | return result
65 | }
66 |
67 | // Each runs a function on every element of the slice
68 | func (s *_SLICERNAME_) Each(fn func(_TYPE_)) {
69 | for _, elem := range s.slice {
70 | fn(elem)
71 | }
72 | }
73 |
74 | // Contains indicates if the given value is in the slice
75 | func (s *_SLICERNAME_) Contains(matcher _TYPE_) bool {
76 | result := false
77 | for _, elem := range s.slice {
78 | if elem == matcher {
79 | result = true
80 | }
81 | }
82 | return result
83 | }
84 |
85 | // Length returns the number of elements in the slice
86 | func (s *_SLICERNAME_) Length() int {
87 | return len(s.slice)
88 | }
89 |
90 | // Clear all elements in the slice
91 | func (s *_SLICERNAME_) Clear() {
92 | s.slice = []_TYPE_{}
93 | }
94 |
95 | // Deduplicate removes duplicate values from the slice
96 | func (s *_SLICERNAME_) Deduplicate() {
97 |
98 | result := &_SLICERNAME_{}
99 |
100 | for _, elem := range s.slice {
101 | if !result.Contains(elem) {
102 | result.Add(elem)
103 | }
104 | }
105 |
106 | s.slice = result.AsSlice()
107 | }
108 |
--------------------------------------------------------------------------------
/string.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "strings"
7 |
8 | // StringSlicer handles slices of string
9 | type StringSlicer struct {
10 | slice []string
11 | }
12 |
13 | // String creates a new StringSlicer
14 | func String(slice ...[]string) *StringSlicer {
15 | if len(slice) > 0 {
16 | return &StringSlicer{slice: slice[0]}
17 | }
18 | return &StringSlicer{}
19 | }
20 |
21 | // Add a string value to the slicer
22 | func (s *StringSlicer) Add(value string, additional ...string) {
23 | s.slice = append(s.slice, value)
24 | s.slice = append(s.slice, additional...)
25 | }
26 |
27 | // AddUnique adds a string value to the slicer if it does not already exist
28 | func (s *StringSlicer) AddUnique(value string, additional ...string) {
29 |
30 | if !s.Contains(value) {
31 | s.slice = append(s.slice, value)
32 | }
33 |
34 | // Add additional values
35 | for _, value := range additional {
36 | if !s.Contains(value) {
37 | s.slice = append(s.slice, value)
38 | }
39 | }
40 | }
41 |
42 | // AddSlice adds a string slice to the slicer
43 | func (s *StringSlicer) AddSlice(value []string) {
44 | s.slice = append(s.slice, value...)
45 | }
46 |
47 | // AsSlice returns the slice
48 | func (s *StringSlicer) AsSlice() []string {
49 | return s.slice
50 | }
51 |
52 | // AddSlicer appends a StringSlicer to the slicer
53 | func (s *StringSlicer) AddSlicer(value *StringSlicer) {
54 | s.slice = append(s.slice, value.AsSlice()...)
55 | }
56 |
57 | // Filter the slice based on the given function
58 | func (s *StringSlicer) Filter(fn func(string) bool) *StringSlicer {
59 | result := &StringSlicer{}
60 | for _, elem := range s.slice {
61 | if fn(elem) {
62 | result.Add(elem)
63 | }
64 | }
65 | return result
66 | }
67 |
68 | // Each runs a function on every element of the slice
69 | func (s *StringSlicer) Each(fn func(string)) {
70 | for _, elem := range s.slice {
71 | fn(elem)
72 | }
73 | }
74 |
75 | // Contains indicates if the given value is in the slice
76 | func (s *StringSlicer) Contains(matcher string) bool {
77 | result := false
78 | for _, elem := range s.slice {
79 | if elem == matcher {
80 | result = true
81 | }
82 | }
83 | return result
84 | }
85 |
86 | // Length returns the number of elements in the slice
87 | func (s *StringSlicer) Length() int {
88 | return len(s.slice)
89 | }
90 |
91 | // Clear all elements in the slice
92 | func (s *StringSlicer) Clear() {
93 | s.slice = []string{}
94 | }
95 |
96 | // Deduplicate removes duplicate values from the slice
97 | func (s *StringSlicer) Deduplicate() {
98 |
99 | result := &StringSlicer{}
100 |
101 | for _, elem := range s.slice {
102 | if !result.Contains(elem) {
103 | result.Add(elem)
104 | }
105 | }
106 |
107 | s.slice = result.AsSlice()
108 | }
109 |
110 | // Join returns a string with the slicer elements separated by the given separator
111 | func (s *StringSlicer) Join(separator string) string {
112 | return strings.Join(s.slice, separator)
113 | }
114 |
115 | // Sort the slice values
116 | func (s *StringSlicer) Sort() {
117 | sort.Strings(s.slice)
118 | }
119 |
--------------------------------------------------------------------------------
/string_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "strings"
5 | "testing"
6 | )
7 |
8 | func TestStringFilter(t *testing.T) {
9 |
10 | s := String()
11 | s.Add("one")
12 | s.Add("two")
13 | s.Add("one")
14 | s.Add("three")
15 | s.Add("one")
16 |
17 | expected := "one one one"
18 | filtered := s.Filter(func(v string) bool {
19 | return v == "one"
20 | })
21 | actual := strings.Join(filtered.AsSlice(), " ")
22 | if expected != actual {
23 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
24 | }
25 | }
26 |
27 | func TestStringEach(t *testing.T) {
28 |
29 | s := String()
30 | s.Add("one")
31 | s.Add("two")
32 | s.Add("three")
33 |
34 | result := String()
35 | s.Each(func(elem string) {
36 | result.Add(elem + "!")
37 | })
38 | expected := "one! two! three!"
39 | actual := strings.Join(result.AsSlice(), " ")
40 | if expected != actual {
41 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
42 | }
43 | }
44 |
45 | // TestOptionalStringSlice tests when you construct a String with
46 | // an existing slice
47 | func TestOptionalStringSlice(t *testing.T) {
48 | data := []string{"one", "two", "three"}
49 | s := String(data)
50 |
51 | result := ""
52 | s.Each(func(elem string) {
53 | result += elem
54 | })
55 | expected := "onetwothree"
56 | if expected != result {
57 | t.Errorf("Expected '%s', but got '%s'", expected, result)
58 | }
59 | }
60 |
61 | // TestSort tests that the slicer can be sorted
62 | func TestSort(t *testing.T) {
63 | data := []string{"cat", "bat", "dog", "arachnid"}
64 | s := String(data)
65 | s.Sort()
66 | result := ""
67 | s.Each(func(elem string) {
68 | result += elem
69 | })
70 | expected := "arachnidbatcatdog"
71 | if expected != result {
72 | t.Errorf("Expected '%s', but got '%s'", expected, result)
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/uint.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // UintSlicer handles slices of uint
10 | type UintSlicer struct {
11 | slice []uint
12 | }
13 |
14 | // Uint creates a new UintSlicer
15 | func Uint(slice ...[]uint) *UintSlicer {
16 | if len(slice) > 0 {
17 | return &UintSlicer{slice: slice[0]}
18 | }
19 | return &UintSlicer{}
20 | }
21 |
22 | // Add a uint value to the slicer
23 | func (s *UintSlicer) Add(value uint, additional ...uint) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a uint value to the slicer if it does not already exist
29 | func (s *UintSlicer) AddUnique(value uint, additional ...uint) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a uint slice to the slicer
44 | func (s *UintSlicer) AddSlice(value []uint) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *UintSlicer) AsSlice() []uint {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a UintSlicer to the slicer
54 | func (s *UintSlicer) AddSlicer(value *UintSlicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *UintSlicer) Filter(fn func(uint) bool) *UintSlicer {
60 | result := &UintSlicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *UintSlicer) Each(fn func(uint)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *UintSlicer) Contains(matcher uint) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *UintSlicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *UintSlicer) Clear() {
94 | s.slice = []uint{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *UintSlicer) Deduplicate() {
99 |
100 | result := &UintSlicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *UintSlicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *UintSlicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/uint16.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Uint16Slicer handles slices of uint16
10 | type Uint16Slicer struct {
11 | slice []uint16
12 | }
13 |
14 | // Uint16 creates a new Uint16Slicer
15 | func Uint16(slice ...[]uint16) *Uint16Slicer {
16 | if len(slice) > 0 {
17 | return &Uint16Slicer{slice: slice[0]}
18 | }
19 | return &Uint16Slicer{}
20 | }
21 |
22 | // Add a uint16 value to the slicer
23 | func (s *Uint16Slicer) Add(value uint16, additional ...uint16) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a uint16 value to the slicer if it does not already exist
29 | func (s *Uint16Slicer) AddUnique(value uint16, additional ...uint16) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a uint16 slice to the slicer
44 | func (s *Uint16Slicer) AddSlice(value []uint16) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Uint16Slicer) AsSlice() []uint16 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Uint16Slicer to the slicer
54 | func (s *Uint16Slicer) AddSlicer(value *Uint16Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Uint16Slicer) Filter(fn func(uint16) bool) *Uint16Slicer {
60 | result := &Uint16Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Uint16Slicer) Each(fn func(uint16)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Uint16Slicer) Contains(matcher uint16) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Uint16Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Uint16Slicer) Clear() {
94 | s.slice = []uint16{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Uint16Slicer) Deduplicate() {
99 |
100 | result := &Uint16Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Uint16Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Uint16Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/uint16_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "github.com/matryer/is"
6 | "testing"
7 | )
8 |
9 | func TestUint16Add(t *testing.T) {
10 |
11 | s := Uint16()
12 | s.Add(1)
13 | s.Add(2)
14 |
15 | expected := "[1,2]"
16 | actual, _ := json.Marshal(s.AsSlice())
17 | if expected != string(actual) {
18 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
19 | }
20 |
21 | s.Clear()
22 | s.Add(1, 2)
23 |
24 | expected = "[1,2]"
25 | actual, _ = json.Marshal(s.AsSlice())
26 | if expected != string(actual) {
27 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
28 | }
29 | }
30 |
31 | func TestUint16Length(t *testing.T) {
32 | is2 := is.New(t)
33 | s := Uint16()
34 | s.Add(1)
35 | s.Add(2)
36 |
37 | is2.Equal(s.Length(), 2)
38 | }
39 | func TestUint16Deduplicate(t *testing.T) {
40 | is2 := is.New(t)
41 | s := Uint16()
42 | s.Add(1)
43 | s.Add(2)
44 | s.Add(2)
45 | s.Add(2)
46 |
47 | is2.Equal(s.Length(), 4)
48 | is2.Equal(s.AsSlice(), []uint16{1, 2, 2, 2})
49 | s.Deduplicate()
50 | is2.Equal(s.Length(), 2)
51 | is2.Equal(s.AsSlice(), []uint16{1, 2})
52 | }
53 | func TestUint16AddUnique(t *testing.T) {
54 |
55 | s := Uint16()
56 | s.AddUnique(1)
57 | s.AddUnique(2)
58 | s.AddUnique(2)
59 | s.AddUnique(2)
60 |
61 | expected := "[1,2]"
62 | actual, _ := json.Marshal(s.AsSlice())
63 | if expected != string(actual) {
64 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
65 | }
66 |
67 | s.Clear()
68 | s.AddUnique(1, 2, 1, 2, 2, 1)
69 |
70 | expected = "[1,2]"
71 | actual, _ = json.Marshal(s.AsSlice())
72 | if expected != string(actual) {
73 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
74 | }
75 | }
76 |
77 | func TestUint16AddSlice(t *testing.T) {
78 |
79 | s := Uint16()
80 | s.Add(1)
81 | s.Add(2)
82 |
83 | extras := []uint16{3, 4}
84 |
85 | s.AddSlice(extras)
86 |
87 | expected := "[1,2,3,4]"
88 | actual, _ := json.Marshal(s.AsSlice())
89 | if expected != string(actual) {
90 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
91 | }
92 | }
93 |
94 | func TestUint16AddSlicer(t *testing.T) {
95 |
96 | s := Uint16()
97 | s.Add(1)
98 | s.Add(2)
99 |
100 | p := Uint16()
101 | p.Add(3)
102 | p.Add(4)
103 |
104 | s.AddSlicer(p)
105 |
106 | expected := "[1,2,3,4]"
107 | actual, _ := json.Marshal(s.AsSlice())
108 | if expected != string(actual) {
109 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
110 | }
111 | }
112 | func TestUint16Filter(t *testing.T) {
113 |
114 | s := Uint16()
115 | s.Add(18)
116 | s.Add(180)
117 | s.Add(1)
118 | s.Add(10)
119 | s.Add(20)
120 | s.Add(3)
121 | s.Add(29)
122 |
123 | result := s.Filter(func(i uint16) bool {
124 | return i > 19
125 | })
126 |
127 | expected := "[180,20,29]"
128 | actual, _ := json.Marshal(result.AsSlice())
129 | if expected != string(actual) {
130 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
131 | }
132 | }
133 | func TestUint16Each(t *testing.T) {
134 |
135 | s := Uint16()
136 | s.Add(18)
137 | s.Add(10)
138 | s.Add(1)
139 | s.Add(10)
140 | s.Add(20)
141 | s.Add(3)
142 | s.Add(29)
143 |
144 | var result uint16
145 |
146 | s.Each(func(i uint16) {
147 | result = result + i
148 | })
149 |
150 | var expected uint16 = 91
151 | if expected != result {
152 | t.Errorf("Expected '%d', but got '%d'", expected, result)
153 | }
154 | }
155 |
156 | // TestOptionalUint16Slice tests when you construct a Uint16 with
157 | // an existing slice
158 | func TestOptionalUint16Slice(t *testing.T) {
159 | data := []uint16{1, 2, 3}
160 | s := Uint16(data)
161 |
162 | var result uint16 = 0
163 | s.Each(func(elem uint16) {
164 | result += elem
165 | })
166 | var expected uint16 = 6
167 | if expected != result {
168 | t.Errorf("Expected '%d', but got '%d'", expected, result)
169 | }
170 | }
171 |
172 | // TestUint16Sort tests that the slicer can be sorted
173 | func TestUint16Sort(t *testing.T) {
174 | is2 := is.New(t)
175 | data := []uint16{5, 4, 3, 2, 1}
176 | s := Uint16(data)
177 | s.Sort()
178 | result := s.Join(",")
179 | expected := "1,2,3,4,5"
180 | is2.Equal(result, expected)
181 | s.Clear()
182 | is2.Equal(s.Join(""), "")
183 | }
184 |
--------------------------------------------------------------------------------
/uint32.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Uint32Slicer handles slices of uint32
10 | type Uint32Slicer struct {
11 | slice []uint32
12 | }
13 |
14 | // Uint32 creates a new Uint32Slicer
15 | func Uint32(slice ...[]uint32) *Uint32Slicer {
16 | if len(slice) > 0 {
17 | return &Uint32Slicer{slice: slice[0]}
18 | }
19 | return &Uint32Slicer{}
20 | }
21 |
22 | // Add a uint32 value to the slicer
23 | func (s *Uint32Slicer) Add(value uint32, additional ...uint32) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a uint32 value to the slicer if it does not already exist
29 | func (s *Uint32Slicer) AddUnique(value uint32, additional ...uint32) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a uint32 slice to the slicer
44 | func (s *Uint32Slicer) AddSlice(value []uint32) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Uint32Slicer) AsSlice() []uint32 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Uint32Slicer to the slicer
54 | func (s *Uint32Slicer) AddSlicer(value *Uint32Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Uint32Slicer) Filter(fn func(uint32) bool) *Uint32Slicer {
60 | result := &Uint32Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Uint32Slicer) Each(fn func(uint32)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Uint32Slicer) Contains(matcher uint32) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Uint32Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Uint32Slicer) Clear() {
94 | s.slice = []uint32{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Uint32Slicer) Deduplicate() {
99 |
100 | result := &Uint32Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Uint32Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Uint32Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/uint32_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "github.com/matryer/is"
6 | "testing"
7 | )
8 |
9 | func TestUint32Add(t *testing.T) {
10 |
11 | s := Uint32()
12 | s.Add(1)
13 | s.Add(2)
14 |
15 | expected := "[1,2]"
16 | actual, _ := json.Marshal(s.AsSlice())
17 | if expected != string(actual) {
18 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
19 | }
20 | s.Clear()
21 | s.Add(1, 2)
22 |
23 | expected = "[1,2]"
24 | actual, _ = json.Marshal(s.AsSlice())
25 | if expected != string(actual) {
26 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
27 | }
28 | }
29 |
30 | func TestUint32AddUnique(t *testing.T) {
31 |
32 | s := Uint32()
33 | s.AddUnique(1)
34 | s.AddUnique(2)
35 | s.AddUnique(2)
36 | s.AddUnique(2)
37 |
38 | expected := "[1,2]"
39 | actual, _ := json.Marshal(s.AsSlice())
40 | if expected != string(actual) {
41 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
42 | }
43 |
44 | s.Clear()
45 | s.AddUnique(1, 2, 1, 2, 2, 1)
46 |
47 | expected = "[1,2]"
48 | actual, _ = json.Marshal(s.AsSlice())
49 | if expected != string(actual) {
50 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
51 | }
52 | }
53 |
54 | func TestUint32AddSlice(t *testing.T) {
55 |
56 | s := Uint32()
57 | s.Add(1)
58 | s.Add(2)
59 |
60 | extras := []uint32{3, 4}
61 |
62 | s.AddSlice(extras)
63 |
64 | expected := "[1,2,3,4]"
65 | actual, _ := json.Marshal(s.AsSlice())
66 | if expected != string(actual) {
67 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
68 | }
69 | }
70 |
71 | func TestUint32Length(t *testing.T) {
72 | is2 := is.New(t)
73 | s := Uint32()
74 | s.Add(1)
75 | s.Add(2)
76 |
77 | is2.Equal(s.Length(), 2)
78 | }
79 |
80 | func TestUint32Deduplicate(t *testing.T) {
81 | is2 := is.New(t)
82 | s := Uint32()
83 | s.Add(1)
84 | s.Add(2)
85 | s.Add(2)
86 | s.Add(2)
87 |
88 | is2.Equal(s.Length(), 4)
89 | is2.Equal(s.AsSlice(), []uint32{1, 2, 2, 2})
90 | s.Deduplicate()
91 | is2.Equal(s.Length(), 2)
92 | is2.Equal(s.AsSlice(), []uint32{1, 2})
93 |
94 | }
95 | func TestUint32AddSlicer(t *testing.T) {
96 |
97 | s := Uint32()
98 | s.Add(1)
99 | s.Add(2)
100 |
101 | p := Uint32()
102 | p.Add(3)
103 | p.Add(4)
104 |
105 | s.AddSlicer(p)
106 |
107 | expected := "[1,2,3,4]"
108 | actual, _ := json.Marshal(s.AsSlice())
109 | if expected != string(actual) {
110 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
111 | }
112 | }
113 |
114 | func TestUint32Filter(t *testing.T) {
115 |
116 | s := Uint32()
117 | s.Add(18)
118 | s.Add(180)
119 | s.Add(1)
120 | s.Add(10)
121 | s.Add(20)
122 | s.Add(3)
123 | s.Add(29)
124 |
125 | result := s.Filter(func(i uint32) bool {
126 | return i > 19
127 | })
128 |
129 | expected := "[180,20,29]"
130 | actual, _ := json.Marshal(result.AsSlice())
131 | if expected != string(actual) {
132 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
133 | }
134 | }
135 |
136 | func TestUint32Each(t *testing.T) {
137 |
138 | s := Uint32()
139 | s.Add(18)
140 | s.Add(10)
141 | s.Add(1)
142 | s.Add(10)
143 | s.Add(20)
144 | s.Add(3)
145 | s.Add(29)
146 |
147 | var result uint32
148 |
149 | s.Each(func(i uint32) {
150 | result = result + i
151 | })
152 |
153 | var expected uint32 = 91
154 | if expected != result {
155 | t.Errorf("Expected '%d', but got '%d'", expected, result)
156 | }
157 | }
158 |
159 | // TestOptionalUint32Slice tests when you construct a Uint32 with
160 | // an existing slice
161 | func TestOptionalUint32Slice(t *testing.T) {
162 | data := []uint32{1, 2, 3}
163 | s := Uint32(data)
164 |
165 | var result uint32 = 0
166 | s.Each(func(elem uint32) {
167 | result += elem
168 | })
169 | var expected uint32 = 6
170 | if expected != result {
171 | t.Errorf("Expected '%d', but got '%d'", expected, result)
172 | }
173 | }
174 |
175 | // TestUint32Sort tests that the slicer can be sorted
176 | func TestUint32Sort(t *testing.T) {
177 | is2 := is.New(t)
178 | data := []uint32{5, 4, 3, 2, 1}
179 | s := Uint32(data)
180 | s.Sort()
181 | result := s.Join(",")
182 | expected := "1,2,3,4,5"
183 | is2.Equal(expected, result)
184 | s.Clear()
185 | is2.Equal(s.Join(""), "")
186 | }
187 |
--------------------------------------------------------------------------------
/uint64.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Uint64Slicer handles slices of uint64
10 | type Uint64Slicer struct {
11 | slice []uint64
12 | }
13 |
14 | // Uint64 creates a new Uint64Slicer
15 | func Uint64(slice ...[]uint64) *Uint64Slicer {
16 | if len(slice) > 0 {
17 | return &Uint64Slicer{slice: slice[0]}
18 | }
19 | return &Uint64Slicer{}
20 | }
21 |
22 | // Add a uint64 value to the slicer
23 | func (s *Uint64Slicer) Add(value uint64, additional ...uint64) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a uint64 value to the slicer if it does not already exist
29 | func (s *Uint64Slicer) AddUnique(value uint64, additional ...uint64) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a uint64 slice to the slicer
44 | func (s *Uint64Slicer) AddSlice(value []uint64) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Uint64Slicer) AsSlice() []uint64 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Uint64Slicer to the slicer
54 | func (s *Uint64Slicer) AddSlicer(value *Uint64Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Uint64Slicer) Filter(fn func(uint64) bool) *Uint64Slicer {
60 | result := &Uint64Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Uint64Slicer) Each(fn func(uint64)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Uint64Slicer) Contains(matcher uint64) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Uint64Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Uint64Slicer) Clear() {
94 | s.slice = []uint64{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Uint64Slicer) Deduplicate() {
99 |
100 | result := &Uint64Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Uint64Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Uint64Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/uint64_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "github.com/matryer/is"
6 | "testing"
7 | )
8 |
9 | func TestUint64Add(t *testing.T) {
10 |
11 | s := Uint64()
12 | s.Add(1)
13 | s.Add(2)
14 |
15 | expected := "[1,2]"
16 | actual, _ := json.Marshal(s.AsSlice())
17 | if expected != string(actual) {
18 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
19 | }
20 | s.Clear()
21 | s.Add(1, 2)
22 |
23 | expected = "[1,2]"
24 | actual, _ = json.Marshal(s.AsSlice())
25 | if expected != string(actual) {
26 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
27 | }
28 | }
29 | func TestUint64AddUnique(t *testing.T) {
30 |
31 | s := Uint64()
32 | s.AddUnique(1)
33 | s.AddUnique(2)
34 | s.AddUnique(2)
35 | s.AddUnique(2)
36 |
37 | expected := "[1,2]"
38 | actual, _ := json.Marshal(s.AsSlice())
39 | if expected != string(actual) {
40 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
41 | }
42 |
43 | s.Clear()
44 | s.AddUnique(1, 2, 1, 2, 2, 1)
45 |
46 | expected = "[1,2]"
47 | actual, _ = json.Marshal(s.AsSlice())
48 | if expected != string(actual) {
49 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
50 | }
51 | }
52 |
53 | func TestUint64AddSlice(t *testing.T) {
54 |
55 | s := Uint64()
56 | s.Add(1)
57 | s.Add(2)
58 |
59 | extras := []uint64{3, 4}
60 |
61 | s.AddSlice(extras)
62 |
63 | expected := "[1,2,3,4]"
64 | actual, _ := json.Marshal(s.AsSlice())
65 | if expected != string(actual) {
66 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
67 | }
68 | }
69 |
70 | func TestUint64AddSlicer(t *testing.T) {
71 |
72 | s := Uint64()
73 | s.Add(1)
74 | s.Add(2)
75 |
76 | p := Uint64()
77 | p.Add(3)
78 | p.Add(4)
79 |
80 | s.AddSlicer(p)
81 |
82 | expected := "[1,2,3,4]"
83 | actual, _ := json.Marshal(s.AsSlice())
84 | if expected != string(actual) {
85 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
86 | }
87 | }
88 |
89 | func TestUint64Filter(t *testing.T) {
90 |
91 | s := Uint64()
92 | s.Add(18)
93 | s.Add(180)
94 | s.Add(1)
95 | s.Add(10)
96 | s.Add(20)
97 | s.Add(3)
98 | s.Add(29)
99 |
100 | result := s.Filter(func(i uint64) bool {
101 | return i > 19
102 | })
103 |
104 | expected := "[180,20,29]"
105 | actual, _ := json.Marshal(result.AsSlice())
106 | if expected != string(actual) {
107 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
108 | }
109 | }
110 |
111 | func TestUint64Each(t *testing.T) {
112 |
113 | s := Uint64()
114 | s.Add(18)
115 | s.Add(10)
116 | s.Add(1)
117 | s.Add(10)
118 | s.Add(20)
119 | s.Add(3)
120 | s.Add(29)
121 |
122 | var result uint64
123 |
124 | s.Each(func(i uint64) {
125 | result = result + i
126 | })
127 |
128 | var expected uint64 = 91
129 | if expected != result {
130 | t.Errorf("Expected '%d', but got '%d'", expected, result)
131 | }
132 | }
133 |
134 | // TestOptionalUint64Slice tests when you construct a Uint64 with
135 | // an existing slice
136 | func TestOptionalUint64Slice(t *testing.T) {
137 | data := []uint64{1, 2, 3}
138 | s := Uint64(data)
139 |
140 | var result uint64 = 0
141 | s.Each(func(elem uint64) {
142 | result += elem
143 | })
144 | var expected uint64 = 6
145 | if expected != result {
146 | t.Errorf("Expected '%d', but got '%d'", expected, result)
147 | }
148 | }
149 | func TestUint64Deduplicate(t *testing.T) {
150 | is2 := is.New(t)
151 | s := Uint64()
152 | s.Add(1)
153 | s.Add(2)
154 | s.Add(2)
155 | s.Add(2)
156 |
157 | is2.Equal(s.Length(), 4)
158 | is2.Equal(s.AsSlice(), []uint64{1, 2, 2, 2})
159 | s.Deduplicate()
160 | is2.Equal(s.Length(), 2)
161 | is2.Equal(s.AsSlice(), []uint64{1, 2})
162 | }
163 | func TestUint64Length(t *testing.T) {
164 | is2 := is.New(t)
165 | s := Uint64()
166 | s.Add(1)
167 | s.Add(2)
168 |
169 | is2.Equal(s.Length(), 2)
170 | }
171 |
172 | // TestUint64Sort tests that the slicer can be sorted
173 | func TestUint64Sort(t *testing.T) {
174 | is2 := is.New(t)
175 | data := []uint64{5, 4, 3, 2, 1}
176 | s := Uint64(data)
177 | s.Sort()
178 | result := s.Join(",")
179 | expected := "1,2,3,4,5"
180 | is2.Equal(expected, result)
181 | s.Clear()
182 | is2.Equal(s.Join(""), "")
183 | }
184 |
--------------------------------------------------------------------------------
/uint8.go:
--------------------------------------------------------------------------------
1 | // Package slicer contains utility classes for handling slices
2 | package slicer
3 |
4 | // Imports
5 | import "sort"
6 | import "fmt"
7 | import "strings"
8 |
9 | // Uint8Slicer handles slices of uint8
10 | type Uint8Slicer struct {
11 | slice []uint8
12 | }
13 |
14 | // Uint8 creates a new Uint8Slicer
15 | func Uint8(slice ...[]uint8) *Uint8Slicer {
16 | if len(slice) > 0 {
17 | return &Uint8Slicer{slice: slice[0]}
18 | }
19 | return &Uint8Slicer{}
20 | }
21 |
22 | // Add a uint8 value to the slicer
23 | func (s *Uint8Slicer) Add(value uint8, additional ...uint8) {
24 | s.slice = append(s.slice, value)
25 | s.slice = append(s.slice, additional...)
26 | }
27 |
28 | // AddUnique adds a uint8 value to the slicer if it does not already exist
29 | func (s *Uint8Slicer) AddUnique(value uint8, additional ...uint8) {
30 |
31 | if !s.Contains(value) {
32 | s.slice = append(s.slice, value)
33 | }
34 |
35 | // Add additional values
36 | for _, value := range additional {
37 | if !s.Contains(value) {
38 | s.slice = append(s.slice, value)
39 | }
40 | }
41 | }
42 |
43 | // AddSlice adds a uint8 slice to the slicer
44 | func (s *Uint8Slicer) AddSlice(value []uint8) {
45 | s.slice = append(s.slice, value...)
46 | }
47 |
48 | // AsSlice returns the slice
49 | func (s *Uint8Slicer) AsSlice() []uint8 {
50 | return s.slice
51 | }
52 |
53 | // AddSlicer appends a Uint8Slicer to the slicer
54 | func (s *Uint8Slicer) AddSlicer(value *Uint8Slicer) {
55 | s.slice = append(s.slice, value.AsSlice()...)
56 | }
57 |
58 | // Filter the slice based on the given function
59 | func (s *Uint8Slicer) Filter(fn func(uint8) bool) *Uint8Slicer {
60 | result := &Uint8Slicer{}
61 | for _, elem := range s.slice {
62 | if fn(elem) {
63 | result.Add(elem)
64 | }
65 | }
66 | return result
67 | }
68 |
69 | // Each runs a function on every element of the slice
70 | func (s *Uint8Slicer) Each(fn func(uint8)) {
71 | for _, elem := range s.slice {
72 | fn(elem)
73 | }
74 | }
75 |
76 | // Contains indicates if the given value is in the slice
77 | func (s *Uint8Slicer) Contains(matcher uint8) bool {
78 | result := false
79 | for _, elem := range s.slice {
80 | if elem == matcher {
81 | result = true
82 | }
83 | }
84 | return result
85 | }
86 |
87 | // Length returns the number of elements in the slice
88 | func (s *Uint8Slicer) Length() int {
89 | return len(s.slice)
90 | }
91 |
92 | // Clear all elements in the slice
93 | func (s *Uint8Slicer) Clear() {
94 | s.slice = []uint8{}
95 | }
96 |
97 | // Deduplicate removes duplicate values from the slice
98 | func (s *Uint8Slicer) Deduplicate() {
99 |
100 | result := &Uint8Slicer{}
101 |
102 | for _, elem := range s.slice {
103 | if !result.Contains(elem) {
104 | result.Add(elem)
105 | }
106 | }
107 |
108 | s.slice = result.AsSlice()
109 | }
110 |
111 | // Join returns a string with the slicer elements separated by the given separator
112 | func (s *Uint8Slicer) Join(separator string) string {
113 | var builder strings.Builder
114 |
115 | // Shortcut no elements
116 | if len(s.slice) == 0 {
117 | return ""
118 | }
119 |
120 | // Iterate over length - 1
121 | index := 0
122 | for index = 0; index < len(s.slice)-1; index++ {
123 | builder.WriteString(fmt.Sprintf("%v%s", s.slice[index], separator))
124 | }
125 | builder.WriteString(fmt.Sprintf("%v", s.slice[index]))
126 | result := builder.String()
127 | return result
128 | }
129 |
130 | // Sort the slice values
131 | func (s *Uint8Slicer) Sort() {
132 | sort.Slice(s.slice, func(i, j int) bool { return s.slice[i] < s.slice[j] })
133 | }
134 |
--------------------------------------------------------------------------------
/uint8_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "github.com/matryer/is"
5 | "testing"
6 | )
7 |
8 | func TestUint8Add(t *testing.T) {
9 |
10 | is2 := is.New(t)
11 | s := Uint8()
12 | s.Add(1)
13 | s.Add(2)
14 |
15 | is2.Equal(s.AsSlice(), []uint8{1, 2})
16 |
17 | s.Clear()
18 | s.Add(1, 2)
19 |
20 | is2.Equal(s.AsSlice(), []uint8{1, 2})
21 |
22 | }
23 |
24 | func TestUint8Length(t *testing.T) {
25 | is2 := is.New(t)
26 | s := Uint8()
27 | s.Add(1)
28 | s.Add(2)
29 |
30 | is2.Equal(s.Length(), 2)
31 | }
32 |
33 | func TestUint8AddUnique(t *testing.T) {
34 | is2 := is.New(t)
35 | s := Uint8()
36 | s.AddUnique(1)
37 | s.AddUnique(2)
38 | s.AddUnique(2)
39 | s.AddUnique(2)
40 |
41 | is2.Equal(s.AsSlice(), []uint8{1, 2})
42 |
43 | s.Clear()
44 | s.AddUnique(1, 2, 1, 2, 2, 1)
45 |
46 | is2.Equal(s.AsSlice(), []uint8{1, 2})
47 | }
48 |
49 | func TestUint8Deduplicate(t *testing.T) {
50 | is2 := is.New(t)
51 | s := Uint8()
52 | s.Add(1)
53 | s.Add(2)
54 | s.Add(2)
55 | s.Add(2)
56 |
57 | is2.Equal(s.Length(), 4)
58 | is2.Equal(s.AsSlice(), []uint8{1, 2, 2, 2})
59 | s.Deduplicate()
60 | is2.Equal(s.Length(), 2)
61 | is2.Equal(s.AsSlice(), []uint8{1, 2})
62 | }
63 |
64 | func TestUint8AddSlice(t *testing.T) {
65 | is2 := is.New(t)
66 |
67 | s := Uint8()
68 | s.Add(1)
69 | s.Add(2)
70 |
71 | extras := []uint8{3, 4}
72 |
73 | s.AddSlice(extras)
74 | is2.Equal(s.AsSlice(), []uint8{1, 2, 3, 4})
75 | }
76 |
77 | func TestUint8AddSlicer(t *testing.T) {
78 |
79 | is2 := is.New(t)
80 |
81 | s := Uint8()
82 | s.Add(1)
83 | s.Add(2)
84 |
85 | p := Uint8()
86 | p.Add(3)
87 | p.Add(4)
88 |
89 | s.AddSlicer(p)
90 |
91 | is2.Equal(s.AsSlice(), []uint8{1, 2, 3, 4})
92 | }
93 |
94 | func TestUint8Filter(t *testing.T) {
95 |
96 | is2 := is.New(t)
97 | s := Uint8()
98 | s.Add(18)
99 | s.Add(120)
100 | s.Add(1)
101 | s.Add(10)
102 | s.Add(20)
103 | s.Add(3)
104 | s.Add(29)
105 |
106 | result := s.Filter(func(i uint8) bool {
107 | return i > 19
108 | })
109 |
110 | is2.Equal(result.AsSlice(), []uint8{120, 20, 29})
111 |
112 | }
113 |
114 | func TestUint8Each(t *testing.T) {
115 |
116 | is2 := is.New(t)
117 | s := Uint8()
118 | s.Add(18)
119 | s.Add(10)
120 | s.Add(1)
121 | s.Add(10)
122 | s.Add(20)
123 | s.Add(3)
124 | s.Add(29)
125 |
126 | var result uint8
127 |
128 | s.Each(func(i uint8) {
129 | result = result + i
130 | })
131 | var expected uint8 = 91
132 | is2.Equal(result, expected)
133 | }
134 |
135 | // TestOptionalUint8Slice tests when you construct a Uint8 with
136 | // an existing slice
137 | func TestOptionalUint8Slice(t *testing.T) {
138 | is2 := is.New(t)
139 |
140 | data := []uint8{1, 2, 3}
141 | s := Uint8(data)
142 |
143 | var result uint8 = 0
144 | s.Each(func(elem uint8) {
145 | result += elem
146 | })
147 | var expected uint8 = 6
148 | is2.Equal(result, expected)
149 |
150 | }
151 |
152 | // TestUint8Sort tests that the slicer can be sorted
153 | func TestUint8Sort(t *testing.T) {
154 | is2 := is.New(t)
155 |
156 | data := []uint8{5, 4, 3, 2, 1}
157 | s := Uint8(data)
158 | s.Sort()
159 | result := s.Join(",")
160 | expected := "1,2,3,4,5"
161 | is2.Equal(result, expected)
162 | s.Clear()
163 | is2.Equal(s.Join(""), "")
164 | }
165 |
--------------------------------------------------------------------------------
/uint_test.go:
--------------------------------------------------------------------------------
1 | package slicer
2 |
3 | import (
4 | "encoding/json"
5 | "github.com/matryer/is"
6 | "testing"
7 | )
8 |
9 | func TestUintAdd(t *testing.T) {
10 |
11 | s := Uint()
12 | s.Add(1)
13 | s.Add(2)
14 |
15 | expected := "[1,2]"
16 | actual, _ := json.Marshal(s.AsSlice())
17 | if expected != string(actual) {
18 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
19 | }
20 |
21 | s.Clear()
22 | s.Add(1, 2)
23 |
24 | expected = "[1,2]"
25 | actual, _ = json.Marshal(s.AsSlice())
26 | if expected != string(actual) {
27 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
28 | }
29 | }
30 | func TestUintDeduplicate(t *testing.T) {
31 | is2 := is.New(t)
32 | s := Uint()
33 | s.Add(1)
34 | s.Add(2)
35 | s.Add(2)
36 | s.Add(2)
37 |
38 | is2.Equal(s.Length(), 4)
39 | is2.Equal(s.AsSlice(), []uint{1, 2, 2, 2})
40 | s.Deduplicate()
41 | is2.Equal(s.Length(), 2)
42 | is2.Equal(s.AsSlice(), []uint{1, 2})
43 | }
44 |
45 | func TestUintLength(t *testing.T) {
46 | is2 := is.New(t)
47 | s := Uint()
48 | s.Add(1)
49 | s.Add(2)
50 |
51 | is2.Equal(s.Length(), 2)
52 | }
53 |
54 | func TestUintAddUnique(t *testing.T) {
55 |
56 | s := Uint()
57 | s.AddUnique(1)
58 | s.AddUnique(2)
59 | s.AddUnique(2)
60 | s.AddUnique(2)
61 |
62 | expected := "[1,2]"
63 | actual, _ := json.Marshal(s.AsSlice())
64 | if expected != string(actual) {
65 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
66 | }
67 |
68 | s.Clear()
69 | s.AddUnique(1, 2, 1, 2, 2, 1)
70 |
71 | expected = "[1,2]"
72 | actual, _ = json.Marshal(s.AsSlice())
73 | if expected != string(actual) {
74 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
75 | }
76 | }
77 |
78 | func TestUintAddSlice(t *testing.T) {
79 |
80 | s := Uint()
81 | s.Add(1)
82 | s.Add(2)
83 |
84 | extras := []uint{3, 4}
85 |
86 | s.AddSlice(extras)
87 |
88 | expected := "[1,2,3,4]"
89 | actual, _ := json.Marshal(s.AsSlice())
90 | if expected != string(actual) {
91 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
92 | }
93 | }
94 |
95 | func TestUintAddSlicer(t *testing.T) {
96 |
97 | s := Uint()
98 | s.Add(1)
99 | s.Add(2)
100 |
101 | p := Uint()
102 | p.Add(3)
103 | p.Add(4)
104 |
105 | s.AddSlicer(p)
106 |
107 | expected := "[1,2,3,4]"
108 | actual, _ := json.Marshal(s.AsSlice())
109 | if expected != string(actual) {
110 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
111 | }
112 | }
113 |
114 | func TestUintFilter(t *testing.T) {
115 |
116 | s := Uint()
117 | s.Add(18)
118 | s.Add(120)
119 | s.Add(1)
120 | s.Add(10)
121 | s.Add(20)
122 | s.Add(3)
123 | s.Add(29)
124 |
125 | result := s.Filter(func(i uint) bool {
126 | return i > 19
127 | })
128 |
129 | expected := "[120,20,29]"
130 | actual, _ := json.Marshal(result.AsSlice())
131 | if expected != string(actual) {
132 | t.Errorf("Expected '%s', but got '%s'", expected, actual)
133 | }
134 | }
135 |
136 | // TestOptionalUintSlice tests when you construct a Uint with
137 | // an existing slice
138 | func TestOptionalUintSlice(t *testing.T) {
139 | data := []uint{1, 2, 3}
140 | s := Uint(data)
141 |
142 | var result uint = 0
143 | s.Each(func(elem uint) {
144 | result += elem
145 | })
146 | var expected uint = 6
147 | if expected != result {
148 | t.Errorf("Expected '%d', but got '%d'", expected, result)
149 | }
150 | }
151 |
152 | // TestUintSort tests that the slicer can be sorted
153 | func TestUintSort(t *testing.T) {
154 | is2 := is.New(t)
155 | data := []uint{5, 4, 3, 2, 1}
156 | s := Uint(data)
157 | s.Sort()
158 | result := s.Join(",")
159 | expected := "1,2,3,4,5"
160 | is2.Equal(expected, result)
161 | s.Clear()
162 | is2.Equal(s.Join(""), "")
163 | }
164 |
--------------------------------------------------------------------------------