From 4e6777ff2675af3401dd56284ad7991dbbf0b273 Mon Sep 17 00:00:00 2001 From: Shivam Rathore Date: Mon, 24 Sep 2018 21:58:29 +0530 Subject: [PATCH] feat: Added support for sorting --- README.md | 13 +++++ templates/_ComplexType/sort.go | 40 +++++++++++++ templates/_SimpleType/sort.go | 39 +++++++++++++ tests/sort_test.go | 102 +++++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 templates/_ComplexType/sort.go create mode 100644 templates/_SimpleType/sort.go create mode 100644 tests/sort_test.go diff --git a/README.md b/README.md index cd8493e..891e1dc 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Some of the motivation behind this library is discussed in this [blog post](http * [`DropRight`](#_droprightslice-n) * [`Chain`](#_chainsliceactionactionvalue) * [`Value`](#_chainsliceactionactionvalue) +* [`Sort`](#_sortslice)   #### `_.Reverse(slice)` @@ -130,6 +131,18 @@ _int.Chain([]int{1, 2, 1, 3}).Uniq().Reverse().Value() // => []int{3, 2, 1} ``` +#### `_.Sort(slice, func)` + +Returns a new array of all elements in their sorted order according to the provided comparison function. + +```go +compare := func (a, b int) bool { + return a < b +} +_int.Sort([]int{2, 5, 8, 0, 1}, compare) +// => []int{0, 1, 2, 5, 8} +``` +   ## Working with different types diff --git a/templates/_ComplexType/sort.go b/templates/_ComplexType/sort.go new file mode 100644 index 0000000..e3ff6e0 --- /dev/null +++ b/templates/_ComplexType/sort.go @@ -0,0 +1,40 @@ +package __ComplexType + +import ( + . "_ImportLocation" + "sort" +) + +// Type ... +type Type struct { + typ []_ComplexType + cmp func(a, b _ComplexType) bool +} + +func (obj Type) Len() int { + return len(obj.typ) +} + +func (obj Type) Swap(i, j int) { + obj.typ[i], obj.typ[j] = obj.typ[j], obj.typ[i] +} + +func (obj Type) Less(i, j int) bool { + return obj.cmp(obj.typ[i], obj.typ[j]) +} + +// Sort ... +func Sort(slice []_ComplexType, cmp func(a, b _ComplexType) bool) (res []_ComplexType) { + res = make([]_ComplexType, 0, len(slice)) + res = append(res, slice...) + val := Type{ + typ: res, + cmp: cmp, + } + sort.Sort(val) + return +} + +func (c *chain) Sort(cmp func(a, b _ComplexType) bool) *chain { + return &chain{value: Sort(c.value, cmp)} +} diff --git a/templates/_SimpleType/sort.go b/templates/_SimpleType/sort.go new file mode 100644 index 0000000..9aa0008 --- /dev/null +++ b/templates/_SimpleType/sort.go @@ -0,0 +1,39 @@ +package __SimpleType + +import ( + "sort" +) + +// Type ... +type Type struct { + typ []_SimpleType + cmp func(a, b _SimpleType) bool +} + +func (obj Type) Len() int { + return len(obj.typ) +} + +func (obj Type) Swap(i, j int) { + obj.typ[i], obj.typ[j] = obj.typ[j], obj.typ[i] +} + +func (obj Type) Less(i, j int) bool { + return obj.cmp(obj.typ[i], obj.typ[j]) +} + +// Sort ... +func Sort(slice []_SimpleType, cmp func(a, b _SimpleType) bool) (res []_SimpleType) { + res = make([]_SimpleType, 0, len(slice)) + res = append(res, slice...) + val := Type{ + typ: res, + cmp: cmp, + } + sort.Sort(val) + return +} + +func (c *chain) Sort(cmp func(a, b _SimpleType) bool) *chain { + return &chain{value: Sort(c.value, cmp)} +} diff --git a/tests/sort_test.go b/tests/sort_test.go new file mode 100644 index 0000000..3a3bd5a --- /dev/null +++ b/tests/sort_test.go @@ -0,0 +1,102 @@ +package tests + +import ( + "reflect" + "testing" + + "github.com/go-dash/slice/_Person" // github.com/go-dash/slice/tests/types + "github.com/go-dash/slice/_int" + "github.com/go-dash/slice/_string" + . "github.com/go-dash/slice/tests/types" +) + +var tableSortString = []struct { + input []string + output []string +}{ + {nil, []string{}}, + {[]string{}, []string{}}, + {[]string{"one", "two", "three", "four"}, []string{"four", "one", "three", "two"}}, +} + +func TestSortString(t *testing.T) { + for _, tt := range tableSortString { + res := _string.Sort(tt.input, func(a, b string) bool { + return a <= b + }) + if !reflect.DeepEqual(res, tt.output) { + t.Fatalf("Expected %v received %v", tt.output, res) + } + res = _string.Chain(tt.input).Sort(func(a, b string) bool { + return a <= b + }).Value() + if !reflect.DeepEqual(res, tt.output) { + t.Fatalf("Expected %v received %v", tt.output, res) + } + } +} + +var tableSortInt = []struct { + input []int + output []int +}{ + {nil, []int{}}, + {[]int{}, []int{}}, + {[]int{10, 2, 5, 8, 5, 6}, []int{2, 5, 5, 6, 8, 10}}, +} + +func TestSortInt(t *testing.T) { + for _, tt := range tableSortInt { + res := _int.Sort(tt.input, func(a, b int) bool { + return a <= b + }) + if !reflect.DeepEqual(res, tt.output) { + t.Fatalf("Expected %v received %v", tt.output, res) + } + res = _int.Chain(tt.input).Sort(func(a, b int) bool { + return a <= b + }).Value() + if !reflect.DeepEqual(res, tt.output) { + t.Fatalf("Expected %v received %v", tt.output, res) + } + } +} + +var tableSortPerson = []struct { + input []Person + output []Person +}{ + {nil, []Person{}}, + {[]Person{}, []Person{}}, + { + []Person{Person{"das", 1018}, Person{"sdbb", 109}, Person{"fecc", 122}, Person{"adad", 122}, Person{"rfaa", 122}, Person{"bb", 1209}, Person{"cc", 250}, Person{"dd", 210}}, + []Person{Person{"sdbb", 109}, Person{"adad", 122}, Person{"fecc", 122}, Person{"rfaa", 122}, Person{"dd", 210}, Person{"cc", 250}, Person{"das", 1018}, Person{"bb", 1209}}, + }, +} + +func TestSortPerson(t *testing.T) { + for _, tt := range tableSortPerson { + res := _Person.Sort(tt.input, func(a, b Person) bool { + if a.Age < b.Age { + return true + } else if a.Age > b.Age { + return false + } + return a.Name < b.Name + }) + if !reflect.DeepEqual(res, tt.output) { + t.Fatalf("Expected %v received %v", tt.output, res) + } + res = _Person.Chain(tt.input).Sort(func(a, b Person) bool { + if a.Age < b.Age { + return true + } else if a.Age > b.Age { + return false + } + return a.Name < b.Name + }).Value() + if !reflect.DeepEqual(res, tt.output) { + t.Fatalf("Expected %v received %v", tt.output, res) + } + } +}